判断两个图是否是同构图
题目大意:给你两个图的顶点数和边数组成两个图,问两个图是否是同构图。
首先两个图如果是同构图,那么顶点数和边数要相同。根据题中所给的信息可以得出构成的图可能是有好几个连通分量,我们可以用并查集加排序依次判断这些连通分量的顶点数是否相同,但是还要判断边数也是否一致,比如说下面这个样例
5 4 1 2 2 3 3 1 4 5 5 4 1 2 2 3 4 5 5 4
所以我们还要判断一下每个连通分量是环还是链,判断方法是,当我们用并查集连接两个顶点时,发现这两个顶点的根已经相同了,那么再加上这条边就会形成环。最后排序完判断时,判断一下顶点数是否相同,环和链是否相同就好了。
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<string>
#include<algorithm>
#define inf 0x3fffffff
using 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;
}