(严格)次小生成树
思想很简单:
先建出一棵最小生成树,满足使用的边都是最小的,剩下的边(称为非树边)一定没有树边优。
如果我们加入一条非树边,删除最小生成树中的一条边,次小生成树一定是包括在以这种方法建出的树中的(倘若删两条树边加两条非树边,则肯定没有删一条加一条优,绝不是次小生成树)。
做法:
对于每一条非树边,其边的两端点为 (\(x\) , \(y\)),加入到最小生成树中,则一定会构成一个环。

这时删除环中除了新边以外最大的边,就构成了新的生成树。

删去\(\Downarrow\)

则新树有可能是次小生成树。
可以发现,在环中找最大边可以看为找 \(x\Rightarrow y\) 路径上的最大边。
即从x,y找LCA的同时记录最大边。
可以用树上倍增、树剖来维护。
对于严格次小生成树,再维护一个次大边,在最大边等于新边时,删去次大边。
严格次小生成树code:
坑好多
const int N=1e6+10;
int n,m,x,y,z,k,tt,cnt,mint,dep[N],fa[N],head[N],jd[N],mx[N][24],mxx[N][24],f[N][24];
struct node{
int u,v,w,nxt;
}a[N];
struct Node{
int u,v,w;
}e[N];
void add(int u,int v,int w){
a[++cnt]=(node){u,v,w,head[u]};
head[u]=cnt;
}
int cmp(Node x,Node y){
return x.w<y.w;
}
void dfs(int x,int fat){//分层
f[x][0]=fat;
dep[x]=dep[fat]+1;
for(int i=1;(1<<i)<=dep[x];++i){//Wrong
f[x][i]=f[f[x][i-1]][i-1];
}
for(int i=head[x];i;i=a[i].nxt){
int v=a[i].v;
if(v==fat)continue;
mx[v][0]=a[i].w;
dfs(v,x);
}
}
void init(){//倍增预处理
rep(j,1,21){
for(int i=1;i+(1<<j)-1<=n;i++){
mx[i][j]=Max(mx[i][j-1],mx[f[i][j-1]][j-1]);
mxx[i][j]=Max(mxx[i][j-1],mxx[f[i][j-1]][j-1]);
if(mx[i][j-1]!=mx[f[i][j-1]][j-1]) mxx[i][j]=Max(Min(mx[i][j-1],mx[f[i][j-1]][j-1]),mxx[i][j]);
}
}
}
int LCA(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
For(i,20,0)
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
if(x==y)return x;
For(i,20,0){
if(f[x][i]!=f[y][i]){
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
int Qmax(int u,int v,int w){
int now=0;
if(dep[u]<dep[v])swap(u,v);
For(i,20,0){
if(dep[f[u][i]]>=dep[v]){
if(mx[u][i]==w) now=Max(now,mxx[u][i]);
else now=Max(now,mx[u][i]);
u=f[u][i];
}
}
return now;
}
void work(){
int ans=inf;
rep(i,1,tt){//Wrong
if(!jd[i]){
int u=e[i].u,v=e[i].v,w=e[i].w;//Wrong
int lca=LCA(u,v);
int lmx=Qmax(u,lca,w),rmx=Qmax(v,lca,w);
if(Max(lmx,rmx)!=w) ans=Min(ans,mint+w-Max(lmx,rmx));
}
}
cout<<ans;
}
int find(int x){
if(fa[x]==x)return x;
fa[x]=find(fa[x]);
return fa[x];
}
void un(int x,int y){
int xx=find(x),yy=find(y);
if(xx!=yy)
fa[xx]=yy;
}
signed main(){
n=read();m=read();
rep(i,1,n) fa[i]=i;
tt=0;
rep(i,1,m){
x=read();y=read();z=read();
if(x==y) continue;//Wrong 未判自环
e[++tt].u=x;e[tt].v=y;e[tt].w=z;
}
sort(e+1,e+1+tt,cmp);
rep(i,1,m){
int u=e[i].u,v=e[i].v;
if(find(u)!=find(v)){
un(u,v);
add(u,v,e[i].w);
add(v,u,e[i].w);
mint+=e[i].w;
++k;
jd[i]=1;
}
if(k==n-1) break;
}
dfs(1,0);
init();
work();
return 0;
}

浙公网安备 33010602011771号