HDU - 3038 How Many Answers Are Wrong 并查集
题解:
emm。
先说一点,这个题目是多组的, 但是我没在题目中看到多组的信息。
然后并查集+前缀和的一个思想。
定义: f(x) = pre[x], S[i] = S[i-1] + a[i]
则 sum[x] = S[x] - S[f(x)]。
每次输入l, r, x的时候, 代表 S[r] - S[l-1] = x
我们先判断一下 f(l-1) 和 f(r)的关系。 如果 f(l-1) == f(r)则说明2个点已经联通了, sum[r] - sum[l-1]的值就是S[r] - S[l-1]了。
如果 f(l-1) != f(r) 则说明至少有一块的关系没有确定。
因为可能会有别的点指向fr所以不能直接将f(x) = f(l),然后直接修改sum[x]这是非法的,并且也会漏下sum[f(x)]的值。
我们就将 sum[f(r)] 的值更新为 s - sum[r] + sum[l-1]。
将pre[f(r)] = f(l-1).
因为直接改了之后 f(f(r)) == f(l-1)了, 所以我们要直接将sum[f(r)]的值修改完整。
压缩路径的时候加上权值。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 2e5 + 100; LL sum[N], pre[N]; int fx[N]; int Find(int x){ if(pre[x] == x) return x; Find(pre[x]); sum[x] += sum[pre[x]]; return pre[x] = Find(pre[x]); } int main(){ int n, m, x, y, s; while(~scanf("%d%d", &n, &m)){ for(int i = 0; i <= n; ++i) sum[i] = 0, pre[i] = i; int ans = 0; for(int _ = 1; _ <= m; ++_){ scanf("%d%d%d", &x, &y, &s); --x; int fx = Find(x); int fy = Find(y); if(fx ^ fy){ pre[fy] = fx; sum[fy] = s - sum[y] + sum[x]; } else { ans += (s != sum[y] - sum[x]); } } cout << ans << endl; } return 0; }