【 HDU 3038 How Many Answers Are Wrong】 并查集好题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038

题目大意:

给你n给整数,m次操作。

每次操作是给出三个整数a,b,c; 子序列a~b的和为c。

找出m次操作中有多少次不合法,不合法的操作舍去。

 

解题思路:

先开一个dis[n]数组,dis[x]记录的是与父节点的距离。

d[x]记录的是[0,x]的和    

dis[x]=d[x]-d[pre[x]];

对于每个操作:

1.如果操作合法,则进行更新。 

  注意:节点小的作为父节点放前面。

2.  如果不合法(前提是父节点相同),即dis[b]-dis[a]不等于c,次数加1.

 

 1 #include <iostream>

 2 #include <cstring>

 3 #include <cstdio>

 4 #include <map>

 5 #include <algorithm>

 6 using namespace std;

 7 

 8 const int maxn=200005;

 9 int pre[maxn];

10 int dis[maxn];

11 

12 int find(int x)

13 {

14     int r=x;

15     if(pre[x]!=x)

16     {

17         r=pre[x];

18         pre[x]=find(pre[x]);

19         dis[x]+=dis[r];

20     }

21     return pre[x];

22 }

23 

24 int main()

25 {

26     int n, m, fa, fb, u, v, c, disa, disb;

27     while(cin >> n >> m)

28     {

29         for(int i=0; i<=n; i++)

30             pre[i]=i;

31         memset(dis,0,sizeof(dis));

32         int ans=0;

33         for(int i=0; i<m; i++)

34         {

35             scanf("%d%d%d",&u,&v,&c);

36             u--;

37             fa=find(u);

38             fb=find(v);

39             if(fa!=fb)

40             {

41                 if(fa<fb)

42                 {

43                     dis[fb]=dis[u]-dis[v]+c;

44                     pre[fb]=fa;

45                 }

46                 else

47                 {

48                     dis[fa]=dis[v]-dis[u]-c;

49                     pre[fa]=fb;

50                 }

51             }

52             else

53             {

54                 disa=dis[u];

55                 disb=dis[v];

56                 if(disb-disa!=c)

57                     ans++;

58             }

59         }

60         cout << ans <<endl;

61     }

62     return 0;

63 }

 

 

 

 

 

 

你可能感兴趣的:(HDU)