Hand in Hand 并查集 同构图

来源:互联网 发布:淘宝联通话费充值便宜 编辑:程序博客网 时间:2024/04/30 00:40

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

题目大意:有N个小朋友,第一次手拉手组成一个图,然后分开后在手拉手组成一个图,判断两个图是否相似

解题思路:由于每个小朋友只有两只手,即每个节点的最大入度为2,对于组成的第一个图,判断有几个环,每个环有几个节点,几个链每个链有几个节点,当然单个点就算是链,然后对结果先按节点大小排序,如果相同,就先链后环排序;对第二个图做同样的处理,然后依次比较即可,代码如下:

#include<stdio.h>#include<algorithm>#include<string.h>#define N 10005using namespace std;struct node{    int f,rank,ring;} s1[N],s2[N]; //f为父节点,rank为集合节点数,ring表示是否成环void init()//初始化{    for(int i=1; i<N; i++)    {        s1[i].f=i;        s2[i].f=i;        s1[i].rank=1;        s2[i].rank=1;        s1[i].ring=0;        s2[i].ring=0;    }}bool cmp(node x,node y)//排序{    if(x.rank<y.rank) return true;    else if(x.rank==y.rank&&x.ring<y.ring) return true;    return false;}int find1(int x)//查找{    if(x==s1[x].f) return x;    return s1[x].f=find1(s1[x].f);}int find2(int x){    if(x==s2[x].f) return x;    return s2[x].f=find2(s2[x].f);}void merge1(int x,int y)//合并{    int fx=find1(x);    int fy=find1(y);    if(fx==fy)    {        s1[fx].ring=1;        return;    }    if(s1[fx].rank>s1[fy].rank)    {        s1[fx].rank+=s1[fy].rank;        s1[fy].f=fx;    }    else    {        s1[fy].rank+=s1[fx].rank;        s1[fx].f=fy;    }}void merge2(int x,int y){    int fx=find2(x);    int fy=find2(y);    if(fx==fy)    {        s2[fx].ring=1;        return;    }    if(s2[fx].rank>s2[fy].rank)    {        s2[fx].rank+=s2[fy].rank;        s2[fy].f=fx;    }    else    {        s2[fy].rank+=s2[fx].rank;        s2[fx].f=fy;    }}bool comp(int a)//对比{    sort(s1+1,s1+a+1,cmp);//排序必须从1开始,因为N个节点的话包括N,如果从0开始,只排序到N-1    sort(s2+1,s2+a+1,cmp);    for(int i=1; i<=a; i++)        if(s1[i].rank!=s2[i].rank||s1[i].ring!=s2[i].ring)            return false;    return true;}int main(){    int t,m,x1,n,x2,T=1;    scanf("%d",&t);    while(t--)    {        bool mark=true;        scanf("%d%d",&m,&x1);        init();        int h1,h2;        for(int i=1; i<=x1; i++)        {            scanf("%d%d",&h1,&h2);            merge1(h1,h2);        }        scanf("%d%d",&n,&x2);        if(x1!=x2) mark=false;        for(int i=1; i<=x2; i++)        {            scanf("%d%d",&h1,&h2);            if(!mark) continue;            merge2(h1,h2);        }        if(!mark) printf("Case #%d: NO\n", T++);        else        {            if(comp(m)) printf("Case #%d: YES\n", T++);            else printf("Case #%d: NO\n", T++);        }    }}

此题我纠结了好长时间,因为排序应该从1开始,这样才能排完1~N。。。

0 0
原创粉丝点击