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]。
盗用一张图:
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 }