将边按边权从小到大排序;
如果插入的两个点在一棵树上,就找他们路径上权值最小的那条边并删除,然后在新加一条边
否则直接加就好了
路径需要以点的形式插入到LCT,第i跳路径对于i+n号节点,Link(x,y) 就Link(x,i+n),Link(i+n,y) 就好了
维护一下最小值
#include<bits/stdc++.h>
#define N 1000005
#define lc t[x].ch[0]
#define rc t[x].ch[1]
using namespace std;
struct Node{
int ch[2],Min,fa,tag;
}t[N];
struct Edge{int x,y,val;}E[N];
bool cmp(Edge a,Edge b){return a.val<b.val;}
int n,m,ans=1e9,mi,cnt,vis[N],val[N];
int read(){
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))cnt=cnt*10+(ch-'0'),ch=getchar();
return cnt*f;
}
bool isRoot(int x){
int fa=t[x].fa;
return t[fa].ch[0]!=x && t[fa].ch[1]!=x;
}
void Pushup(int x){
t[x].Min=x;
if(lc && val[t[lc].Min] < val[t[x].Min]) t[x].Min = t[lc].Min;
if(rc && val[t[rc].Min] < val[t[x].Min]) t[x].Min = t[rc].Min;
}
void Pushdown(int x){
if(t[x].tag){
swap(lc,rc);
t[lc].tag^=1;
t[rc].tag^=1;
t[x].tag=0;
}
}
void Pushpath(int x){
if(!isRoot(x)) Pushpath(t[x].fa);
Pushdown(x);
}
void rotate(int x){
int y=t[x].fa,z=t[y].fa;
int k=t[y].ch[1]==x;
if(!isRoot(y)) t[z].ch[t[z].ch[1]==y]=x;
t[x].fa=z;
t[y].ch[k]=t[x].ch[k^1];
t[t[x].ch[k^1]].fa=y;
t[x].ch[k^1]=y,t[y].fa=x;
Pushup(y),Pushup(x);
}
void Splay(int x){
Pushpath(x);
while(!isRoot(x)){
int y=t[x].fa,z=t[y].fa;
if(!isRoot(y))
(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
}
void Access(int x){
for(int y=0;x;y=x,x=t[x].fa)
Splay(x),rc=y,Pushup(x);
}
int Findroot(int x){
Access(x),Splay(x);
while(lc) Pushdown(x),x=lc;
return x;
}
void Makeroot(int x){
Access(x),Splay(x),t[x].tag^=1;
}
void Link(int x,int y){
Makeroot(x),t[x].fa=y;
}
void Cut(int x,int y){
Makeroot(x),Access(y),Splay(y);
t[y].ch[0]=0,t[x].fa=0,Pushup(y);
}
int Split(int x,int y){
Makeroot(x),Access(y),Splay(y);
return t[y].Min;
}
int main(){
n=read(),m=read();
for(int i=1;i<=m;i++){
E[i].x=read() , E[i].y=read() , E[i].val=read();
if(E[i].x==E[i].y) i--,m--;
}
sort(E+1,E+m+1,cmp);
for(int i=0;i<=n;i++) val[i]=1e9;
for(int i=1;i<=m;i++) val[i+n]=E[i].val;
for(int i=1;i<=m;i++){
int x=E[i].x,y=E[i].y;
if(Findroot(x)==Findroot(y)){
int tmp=Split(x,y);
Cut(E[tmp-n].x,tmp),Cut(tmp,E[tmp-n].y);
vis[tmp-n]=0;
Link(x,i+n),Link(i+n,y);
vis[i]=1;
while(!vis[mi]) mi++;
}
else{
cnt++,vis[i]=1;
Link(x,i+n),Link(i+n,y);
}
if(cnt==n-1) ans=min(ans,E[i].val-E[mi].val);
}printf("%d\n",ans); return 0;
}