题解:
lct动态维护最小生成树
每次加边时若这两个之间不连通,那么直接连接
如果这两个点联通,那么就找到这条边上的最大值
如果这个大于当前边,就替换掉
但是需要注意的是lct只能维护点,不能维护边
所以可以把边弄成点
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 500000
ll n,m,num,root,data[maxn],fa[maxn],
leftson[maxn],rightson[maxn];
ll v[maxn],aa[maxn],bb[maxn];
bool rev[maxn];
void down(ll x)
{
if (!rev[x]) return;
swap(leftson[x],rightson[x]); rev[x]=0;
rev[leftson[x]]^=1; rev[rightson[x]]^=1;
}
int se(int x,int y,int z)
{
if (v[x]>=v[y]&&v[x]>=v[z]) return(x);
else if (v[y]>=v[x]&&v[y]>=v[z]) return(y);
else return(z);
}
void updata(ll x)
{
down(x);
data[x]=se(x,data[leftson[x]],data[rightson[x]]);
}
void pushr(ll x)
{
rev[x]^=1;
}
bool pd(ll x)
{
ll y=fa[x];
if (leftson[y]!=x&&rightson[y]!=x) return(false);
else return(true);
}
void rotate(ll x,ll y)
{
ll father=fa[x];
if (y==1)
{
rightson[father]=leftson[x];
if (leftson[x]) fa[leftson[x]]=father;
} else
{
leftson[father]=rightson[x];
if (rightson[x]) fa[rightson[x]]=father;
}
fa[x]=fa[father];
if (pd(father))
{
if (leftson[fa[father]]==father)
leftson[fa[father]]=x; else
rightson[fa[father]]=x;
}
fa[father]=x;
if (y==1) leftson[x]=father; else rightson[x]=father;
updata(father); updata(x);
}
void dfs(ll x)
{
if (pd(x)) dfs(fa[x]);
down(x);
}
void splay(ll x)
{
dfs(x);
ll father=fa[x];
while (pd(x))
{
if (!pd(father))
{
if (x==leftson[father]) rotate(x,2);
else rotate(x,1);
} else
{
if (father==leftson[fa[father]])
{
if (x==leftson[father])
rotate(father,2),rotate(x,2);
else rotate(x,1),rotate(x,2);
} else
{
if (x==rightson[father])
rotate(father,1),rotate(x,1);
else rotate(x,2),rotate(x,1);
}
}
father=fa[x];
}
}
void access(ll x)
{
for (ll y=0;x;y=x,x=fa[x])
splay(x),rightson[x]=y,updata(x);
}
void makeroot(ll x)
{
access(x);
splay(x);
pushr(x);
}
ll findroot(ll x)
{
access(x);
splay(x);
while (leftson[x]) x=leftson[x];
return x;
}
void split(ll x,ll y)
{
makeroot(x);
access(y);
splay(y);
}
void link(ll x,ll y)
{
makeroot(x);
if (findroot(y)!=x) fa[x]=y;
}
void cut(ll x,ll y)
{
makeroot(x);
split(x,y);
fa[x]=leftson[y]=0;
}
int main()
{
freopen("noip.in","r",stdin);
freopen("noip.out","w",stdout);
cin>>n>>m;
int c,d,e;
int cnt=0,num=0;
for (int i=1;i<=m;i++)
{
cin>>c>>d>>e;
makeroot(c);
if (findroot(d)==c)
{
split(c,d);
int d1=data[d];
if (v[d1]>e)
{
cut(aa[d1],d1); cut(bb[d1],d1); num-=(v[d1]-e);
link(c,i+n); link(i+n,d); v[i+n]=e;
aa[i+n]=c; bb[i+n]=d;
}
} else
{
cnt++; link(c,i+n); link(i+n,d); v[i+n]=e;
aa[i+n]=c; bb[i+n]=d; num+=e;
}
}
cout<<num;
return 0;
}