hdu 3172+hdu 3635+hdu 3926

来源:互联网 发布:安卓数据库 编辑:程序博客网 时间:2024/05/18 15:56

题目链接: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             

 

0 0
原创粉丝点击