一道并查集,有对于我比较复杂的地方。看了他们的题解强行理解。利用并查集,用sum【集合的尾数】保存集合的和,合并的时候选小的(左)为父节点。这样遇到边界一样的集合,就可以判断是否冲突。
#include<cstdio>
const int maxn = 200000 + 5;
int sum[maxn];
int pre[maxn], ans;
void init(int n)
{
for(int i = 0; i <= n; i++)
{
sum[i] = 0;
pre[i] = i;
}
ans = 0;
}
int root(int x)
{
if(x == pre[x])
return x;
int t = pre[x];
pre[x] = root(pre[x]);
sum[x] += sum[t];
return pre[x];
}
void merge_set(int s, int e, int v)
{
int fx = root(s);
int fy = root(e);
if(fx == fy)
{
if(sum[e] != sum[s] + v)
ans++;
return;
}
else if(fx > fy)
{
sum[fx] = sum[e] - v - sum[s];
pre[fx] = fy;
}
else
{
sum[fy] = sum[s] + v - sum[e];
pre[fy] = fx;
}
}
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) == 2)
{
init(n);
for(int kase = 1; kase <= m; kase++)
{
int t1, t2, t3;
scanf("%d%d%d", &t1,&t2, &t3);
merge_set(t1 - 1, t2, t3);
}
printf("%d\n", ans);
}
return 0;
}