题意:给你一些人 然后每次输入a b c 表示b在距离a的右边c处 求有多少个矛盾的情况
思路:用sum[a] 代表a点距离根的距离 每次合并时假设根一样 推断sum数组是否符合情况 根不一样 合并两棵树 这里就是带权并查集的精髓
sum[y] = sum[a]-sum[b]+x 这里y的没有合并前b的根
#include <cstdio> #include <cstring> using namespace std; const int maxn = 50010; int f[maxn], flag[maxn], sum[maxn]; int cnt; void init(int n) { for(int i = 1; i <= n; i++) f[i] = i; //memset(rank, 0, sizeof(rank)); memset(sum, 0, sizeof(sum)); } int find(int x) { if(x != f[x]) { int rt = find(f[x]); sum[x] += sum[f[x]]; f[x] = rt; return rt; } return f[x]; } void merge(int i, int j) { int x = find(i); int y = find(j); if(x != y) { f[y] = x; } } int main() { int n, m; while(scanf("%d %d", &n, &m) != EOF) { init(n); int ans = 0; while(m--) { int w, u, v; scanf("%d %d %d", &u, &v, &w); int x = find(u); int y = find(v); if(x != y) { f[y] = x; sum[y] = sum[u] - sum[v] + w; } else { int sum1 = sum[u]; int sum2 = sum[v]; if(sum2-sum1 != w) ans++; } } printf("%d ", ans); } return 0; }