https://www.lydsy.com/JudgeOnline/problem.php?id=1202
带权并查集维护前缀和
s,t,v相当于sum[t]-sum[s-1]=v,那么对于一个连通块中的,val[根节点]=0,val[其他点]等于他们到根节点的距离,用带权并查集维护这个到根节点的距离就可以了,如果不在一个连通块中,设x=find(s-1),y=find(t),由于sum[t]-sum[s-1]=v,那么sum[y]-sum[v]=val[s-1]+v-val[t],也就是两个连通块之间的根节点之间的距离就求出来了。
#include<bits/stdc++.h>
using namespace std;
const int maxl=110;
int n,m,ans;
int f[maxl],val[maxl];
inline void prework()
{
scanf("%d%d",&n,&m);
}
inline int find(int x)
{
if(f[x]==x) return x;
int t=find(f[x]);
val[x]+=val[f[x]];
f[x]=t;
return f[x];
}
inline void mainwork()
{
for(int i=0;i<=n;i++)
f[i]=i,val[i]=0;
int s,t,v,x,y;ans=1;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&s,&t,&v);
s--;
x=find(s);y=find(t);
if(x!=y)
{
f[y]=x;
val[y]=val[s]+v-val[t];
}
else if(val[t]-val[s]!=v)
ans=0;
}
}
inline void print()
{
if(ans)
puts("true");
else
puts("false");
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}