HDU - 3038 How Many Answers Are Wrong 并查集

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;
}
View Code

 

posted @ 2019-07-08 10:01  Schenker  阅读(198)  评论(0编辑  收藏  举报