HDU 3926 Hand in Hand 同构图★

来源:互联网 发布:濮阳市公务员网络 编辑:程序博客网 时间:2024/05/17 06:08

判断两个图是否是同构图

题目大意:给你两个图的顶点数和边数组成两个图,问两个图是否是同构图。

首先两个图如果是同构图,那么顶点数和边数要相同。根据题中所给的信息可以得出构成的图可能是有好几个连通分量,我们可以用并查集加排序依次判断这些连通分量的顶点数是否相同,但是还要判断边数也是否一致,比如说下面这个样例

5 4 1 22 33 14 55 41 22 34 55 4

所以我们还要判断一下每个连通分量是环还是链,判断方法是,当我们用并查集连接两个顶点时,发现这两个顶点的根已经相同了,那么再加上这条边就会形成环。最后排序完判断时,判断一下顶点数是否相同,环和链是否相同就好了。

#include<cstdio>#include<cstring>#include<queue>#include<map>#include<string>#include<algorithm>#define inf 0x3fffffffusing namespace std;const int maxn=20050;int pre1[maxn],pre2[maxn],num1[maxn],num2[maxn],cas=1,book1[maxn],book2[maxn];struct node{    int num;    int tmp;}a[maxn],b[maxn];bool cmp(node a,node b){    if(a.num==b.num)        return a.tmp<b.tmp;    return a.num<b.num;}void creat(){    for(int i=0;i<maxn;i++)    {        pre1[i]=i;        num1[i]=1;        pre2[i]=i;        num2[i]=1;    }}int findroot1(int root){    if(root==pre1[root])return root;    return pre1[root]=findroot1(pre1[root]);}int findroot2(int root){    if(root==pre2[root])return root;    return pre2[root]=findroot2(pre2[root]);}int main(){    int t,n1,m1,n2,m2;    scanf("%d",&t);    while(t--)    {        int flag=0;        int u,v;        creat();        memset(a,0,sizeof(a));        memset(b,0,sizeof(b));        memset(book1,0,sizeof(book1));        memset(book2,0,sizeof(book2));        scanf("%d %d",&n1,&m1);        for(int i=0;i<m1;i++)        {            scanf("%d %d",&u,&v);            int rootu=findroot1(u);            int rootv=findroot1(v);            if(rootu!=rootv)            {                if(rootu>rootv)                    swap(rootu,rootv);                pre1[rootv]=rootu;                num1[rootu]+=num1[rootv];            }            if(rootu==rootv)                book1[rootu]=1;        }        int k1=0,k2=0;        for(int i=1;i<=n1;i++)        {            if(pre1[i]==i)            {                a[k1].num=num1[i];                if(book1[i])                    a[k1].tmp=1;                else                    a[k1].tmp=0;                k1++;            }        }        scanf("%d %d",&n2,&m2);        for(int i=0;i<m2;i++)        {            scanf("%d %d",&u,&v);            int rootu=findroot2(u);            int rootv=findroot2(v);            if(rootu!=rootv)            {                if(rootu>rootv)                    swap(rootu,rootv);                pre2[rootv]=rootu;                num2[rootu]+=num2[rootv];            }            if(rootu==rootv)                book2[rootu]=1;        }        for(int i=1;i<=n2;i++)        {            if(pre2[i]==i)            {                b[k2].num=num2[i];                if(book2[i])                    b[k2].tmp=1;                else                    b[k2].tmp=0;                k2++;            }        }        if(m1!=m2)            flag=1;        if(k1!=k2)            flag=1;       else       {           sort(a,a+k1,cmp);           sort(b,b+k1,cmp);           for(int i=0;i<k1;i++)           {               if(a[i].num!=b[i].num||a[i].tmp!=b[i].tmp)               {                   flag=1;                   break;               }           }       }       printf("Case #%d: ",cas++);       if(!flag)        puts("YES");       else        puts("NO");    }    return 0;}