题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3172
思路:将名字转化为对应的序号就可以,然后就是基本的并查集操作了。。。
View Code
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<map> 6 #include<string> 7 using namespace std; 8 const int MAXN=100000+10; 9 int parent[MAXN]; 10 int n,num; 11 12 int Find(int x){ 13 int s; 14 for(s=x;parent[s]>=0;s=parent[s]); 15 while(s!=x){ 16 int tmp=parent[x]; 17 parent[x]=s; 18 x=tmp; 19 } 20 return s; 21 } 22 23 void Union(int R1,int R2){ 24 int r1=Find(R1); 25 int r2=Find(R2); 26 if(r1==r2)return ; 27 if(parent[r1]>parent[r2]){ 28 parent[r1]+=parent[r2]; 29 parent[r2]=r1; 30 }else { 31 parent[r2]+=parent[r1]; 32 parent[r1]=r2; 33 } 34 } 35 36 37 38 int main(){ 39 int _case; 40 while(~scanf("%d",&_case)){ 41 while(_case--){ 42 scanf("%d",&n); 43 num=1; 44 map<string,int>mp; 45 46 for(int i=1;i<=n;i++){ 47 char s1[22],s2[22]; 48 scanf("%s%s",s1,s2); 49 if(mp.find(s1)==mp.end()){ 50 parent[num]=-1; 51 mp[s1]=num++; 52 } 53 if(mp.find(s2)==mp.end()){ 54 parent[num]=-1; 55 mp[s2]=num++; 56 } 57 Union(mp[s1],mp[s2]); 58 int rt=Find(mp[s1]); 59 printf("%d\n",abs(parent[rt])); 60 } 61 } 62 } 63 return 0; 64 }
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3635
思路:这题的关键之处在于如何求出转移次数。。。其实我们可以在Find()函数中添加一个—_count[]数组来保存每次转移的次数,具体见代码:
View Code
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 using namespace std; 6 const int MAXN=10000+10; 7 int parent[MAXN]; 8 int _count[MAXN]; 9 int Rank[MAXN]; 10 int n,m; 11 12 void Initiate(){ 13 for(int i=1;i<=n;i++){ 14 parent[i]=i; 15 _count[i]=0; 16 Rank[i]=1; 17 } 18 } 19 20 int Find(int x){ 21 if(x==parent[x])return x; 22 else { 23 int tmp=parent[x]; 24 parent[x]=Find(parent[x]); 25 _count[x]+=_count[tmp];//更新转移次数 26 } 27 return parent[x]; 28 } 29 30 31 void Union(int R1,int R2){ 32 int r1=Find(R1); 33 int r2=Find(R2); 34 if(r1==r2)return ; 35 else { 36 parent[r1]=r2; 37 _count[r1]++; 38 Rank[r2]+=Rank[r1]; 39 Rank[r1]=0; 40 } 41 } 42 43 44 int main(){ 45 int _case,t=1; 46 scanf("%d",&_case); 47 while(_case--){ 48 scanf("%d%d",&n,&m); 49 Initiate(); 50 printf("Case %d:\n",t++); 51 for(int i=1;i<=m;i++){ 52 char str[11]; 53 scanf("%s",str); 54 if(str[0]=='T'){ 55 int u,v; 56 scanf("%d%d",&u,&v); 57 Union(u,v); 58 }else if(str[0]=='Q'){ 59 int x; 60 scanf("%d",&x); 61 int y=Find(x); 62 printf("%d %d %d\n",y,Rank[y],_count[x]); 63 } 64 } 65 } 66 return 0; 67 }
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3926
思路:判断两个图是否同构:
首先当然是并查集的一些基本操作了,不过合并的时候应该遵循孩子节点少的合并到孩子节点多的集合中(不然wa),然后就是排序后比较一下就可以了(因为图可能存在环,因此可以先按孩子节点的个数排,然后再按是否存在环排);
View Code
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 const int MAXN=10000+10; 8 int n1,m1,n2,m2; 9 int parent1[MAXN],parent2[MAXN]; 10 struct Graph{ 11 int child; 12 bool ring;//false代表成链,true代表成环 13 }; 14 Graph g1[MAXN],g2[MAXN]; 15 16 void Initiate(){ 17 for(int i=1;i<=n1;i++){ 18 parent1[i]=-1; 19 parent2[i]=-1; 20 g1[i].child=1; 21 g2[i].child=1; 22 g1[i].ring=false; 23 g2[i].ring=false; 24 } 25 } 26 27 int Find(int x,int parent[]){ 28 int s; 29 for(s=x;parent[s]>=0;s=parent[s]); 30 while(s!=x){ 31 int tmp=parent[x]; 32 parent[x]=s; 33 x=tmp; 34 } 35 return s; 36 } 37 38 39 40 void Union(int R1,int R2,int parent[],Graph g[]){ 41 int r1=Find(R1,parent); 42 int r2=Find(R2,parent); 43 if(r1==r2){ 44 g[r1].ring=true;//根结点相同,说明存在环 45 }else { 46 if(g[r1].child>=g[r2].child){ 47 parent[r2]=r1; 48 g[r1].child+=g[r2].child; 49 }else { 50 parent[r1]=r2; 51 g[r2].child+=g[r1].child; 52 } 53 } 54 } 55 56 int cmp(const Graph &g1,const Graph &g2){ 57 if(g1.child!=g2.child){ 58 return g1.child<g2.child; 59 } 60 return g1.ring<g2.ring;//先链后环 61 } 62 63 bool Solve(){ 64 sort(g1+1,g1+n1+1,cmp); 65 sort(g2+1,g2+n2+1,cmp); 66 for(int i=1;i<=n1;i++){ 67 if(g1[i].child!=g2[i].child||(g1[i].child==g2[i].child&&g1[i].ring!=g2[i].ring)) 68 return false; 69 } 70 return true; 71 } 72 73 74 75 int main(){ 76 int _case,t=1; 77 scanf("%d",&_case); 78 while(_case--){ 79 scanf("%d%d",&n1,&m1); 80 Initiate(); 81 bool flag=true; 82 for(int i=1;i<=m1;i++){ 83 int u,v; 84 scanf("%d%d",&u,&v); 85 Union(u,v,parent1,g1); 86 } 87 scanf("%d%d",&n2,&m2); 88 if(m1!=m2||n1!=n2){ 89 flag=false; 90 } 91 for(int i=1;i<=m2;i++){ 92 int u,v; 93 scanf("%d%d",&u,&v); 94 if(!flag)continue; 95 Union(u,v,parent2,g2); 96 } 97 printf("Case #%d: ",t++); 98 if(!flag){ 99 printf("NO\n"); 100 }else { 101 flag=Solve(); 102 if(flag){ 103 printf("YES\n"); 104 }else 105 printf("NO\n"); 106 } 107 } 108 return 0; 109 } 110 111