【 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 }

 

 

 

 

 

 

posted @ 2012-11-03 15:47  Mr. Ant  阅读(278)  评论(0编辑  收藏  举报