XVIII.最小差值生成树
这题\(m^2\)暴力求最小生成树应该是过不去的……估计只有LCT能过去了。
然后就是同IV.[NOI2014]魔法森林一致的方法,排序之后暴力断边连边即可。
注意会有自环!!!虽然我也不知道为什么没判自环算我MLE……
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,res=0x3f3f3f3f;
struct EDGE{
int u,v,w;
friend bool operator <(const EDGE &x,const EDGE &y){
return x.w<y.w;
}
}e[200100];
multiset<int>s;
#define lson t[x].ch[0]
#define rson t[x].ch[1]
struct LCT{
int fa,ch[2],mn,val;
bool rev;
}t[300100];
inline int identify(int x){
if(x==t[t[x].fa].ch[0])return 0;
if(x==t[t[x].fa].ch[1])return 1;
return -1;
}
inline void pushup(int x){
t[x].mn=x;
if(lson&&t[t[x].mn].val>t[t[lson].mn].val)t[x].mn=t[lson].mn;
if(rson&&t[t[x].mn].val>t[t[rson].mn].val)t[x].mn=t[rson].mn;
}
inline void REV(int x){t[x].rev^=1,swap(lson,rson);}
inline void pushdown(int x){
if(!t[x].rev)return;
if(lson)REV(lson);
if(rson)REV(rson);
t[x].rev=0;
}
inline void rotate(int x){
register int y=t[x].fa,z=t[y].fa,dirx=identify(x),diry=identify(y),b=t[x].ch[!dirx];
if(diry!=-1)t[z].ch[diry]=x;t[x].fa=z;
if(b)t[b].fa=y;t[y].ch[dirx]=b;
t[y].fa=x,t[x].ch[!dirx]=y;
pushup(y),pushup(x);
}
inline void pushall(int x){if(identify(x)!=-1)pushall(t[x].fa);pushdown(x);}
inline void splay(int x){for(pushall(x);identify(x)!=-1;rotate(x))if(identify(t[x].fa)!=-1)rotate(identify(x)==identify(t[x].fa)?t[x].fa:x);}
inline void access(int x){for(register int y=0;x;x=t[y=x].fa)splay(x),rson=y,pushup(x);}
inline void makeroot(int x){access(x),splay(x),REV(x);}
inline int findroot(int x){access(x),splay(x),pushdown(x);while(lson)x=lson,pushdown(x);splay(x);return x;}
inline void split(int x,int y){makeroot(x),access(y),splay(y);}
inline void link(int x,int y){makeroot(x),t[x].fa=y;}
inline void cut(int x,int y){split(x,y),t[y].ch[0]=t[x].fa=0,pushup(y);}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)t[i].val=0x3f3f3f3f;
for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
sort(e+1,e+m+1);
for(int i=1;i<=m;i++){
t[i+n].val=e[i].w;
if(findroot(e[i].u)!=findroot(e[i].v))s.insert(e[i].w),link(e[i].u,i+n),link(e[i].v,i+n);
else{
if(e[i].u==e[i].v)continue;
split(e[i].u,e[i].v);
int tmp=t[e[i].v].mn;
cut(e[tmp-n].u,tmp),cut(e[tmp-n].v,tmp),s.erase(s.find(t[tmp].val)),s.insert(e[i].w),link(e[i].u,i+n),link(e[i].v,i+n);
}
if(s.size()==n-1)res=min(res,e[i].w-*s.begin());
}
printf("%d\n",res);
return 0;
}