hdu 3047(带权并查集)

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

思路:冲突的条件是:两个人坐在同一行,同时他们到根节点的差值等于他们之间的差值,这时就产生冲突了。于是我们可以用一个dist数组来保存节点到根的距离,而这个距离在路径压缩的时候更新一下就可以了,dist[x]+=dist[parent[x]]。然后就是合并后的距离,令r1=Find(u),r2=Find(v),于是合并时就有parent[r2]=r1,dist[r2]=dist[u]+w-dist[v]。

盗用一张图:

hdu 3047(带权并查集)

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 using namespace std;

 6 #define MAXN 50000+50

 7 int parent[MAXN];

 8 int dist[MAXN];

 9 int n,m,ans;

10 

11 void Initiate()

12 {

13     memset(dist,0,sizeof(dist));

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

15         parent[i]=i;

16 }

17 

18 int Find(int x)

19 {

20     if(x==parent[x])

21         return x;

22     int tmp=Find(parent[x]);

23     dist[x]+=dist[parent[x]];

24     return parent[x]=tmp;

25 }

26 

27 int Union(int u,int v,int w){

28     int r1=Find(u),r2=Find(v);

29     if(r1==r2&&dist[v]!=dist[u]+w)return 1;

30     parent[r2]=r1;

31     dist[r2]=dist[u]+w-dist[v];

32     return 0;

33 }

34 

35 int main()

36 {

37     int u,v,w;

38     while(~scanf("%d%d",&n,&m))

39     {

40         Initiate();

41         ans=0;

42         while(m--){

43             scanf("%d%d%d",&u,&v,&w);

44             if(Union(u,v,w))ans++;

45         }

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

47     }

48     return 0;

49 }
View Code

 

你可能感兴趣的:(HDU)