HDU-3038-How Many Answers Are Wrong - 种类并查集

题意:

  有兩個人在玩遊戲,有N個數,FF會詢問TT,sum(a, b)=A[a] + ... +A[b]是多少,TT會告訴他正確的答案,也會告訴他錯誤的。要你統計錯誤的答案有多少組。(如果當前的是錯的統計完就直接忽略掉)

总结:这道题花了我很长时间,结果还是看了别人的题解才想到的。其实就是一个小细节,把左区间边界-1。

思路:这题可以用大的值做父节点,也可以用小的值做父节点, 因为合并的值只是表示数组下标罢了。这里我用较小的值做父节点。设父节点是root, 当前节点是node,则sum[node]记录的是node到root这 root-node+1个元素的和。然后在同一颗树里求某一段和,假设求sum(a, b),则 等价于sum[b]-sum[a-1],因而这也可以用作我们的判断是否有误的依据。

AC代码:

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <vector>

 4 using namespace std;

 5 #define maxn 200005

 6 //#define llint long long

 7 int fa[maxn]; int sum[maxn];

 8 int n, m, ans;

 9 void init()

10 {

11    ans = 0;

12    for(int i = 0; i <= n; i++){

13       fa[i] = i;

14       sum[i] = 0;

15    }

16 }

17 int Find(int x)

18 {

19    if(fa[x] == x) {

20       return x;

21    }

22    int t = fa[x];

23    fa[x] = Find(fa[x]);

24    sum[x] += sum[t];

25    return fa[x];

26 }

27 int Union(int a, int b, int s)

28 {

29    int x = Find(a);

30    int y = Find(b);

31    if(x == y&&sum[b]-sum[a] != s) return 1;

32    if(x > y) {

33       fa[x] = y;

34       sum[x] = sum[b] - s - sum[a];

35    }

36    if(x < y) {

37       fa[y] = x;

38       sum[y] = s - sum[b] + sum[a];

39    }

40    return 0;

41 }

42 void work()

43 {

44    for(int i = 0; i < m; i++) {

45       int a, b; int s; scanf("%d%d%d", &a, &b, &s);

46       ans += Union(a-1, b, s);

47    }

48    printf("%d\n", ans);

49 }

50 int main()

51 {

52    while(scanf("%d%d", &n, &m) != EOF){

53       init();

54       work();

55    }

56    return 0;

57 }
View Code

 

你可能感兴趣的:(HDU)