这道题的题意很简单,判断两个图是否是同构的。因为我的经验比较匮乏,首先想到比较度数,然后默默的WA了....之后想到了并查集一个一个判断,接着WA,此时我才想到一个人只能和其他两个人握手,所以只需要判断一下各个并查集匹配的状态,
可以想到一个并查集内的点状态只有两种,1.环,2.链。所以我们可以用0,1来表示这两种状态。因为是匹配并查集,所以我通过优先队列来直接省略了排序环节(有点懒....)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <queue>
#include <functional>
#include <algorithm>
#define N 10005
using namespace std;
int G1[N],G2[N],rank1[N],rank2[N],circle1[N],circle2[N];
struct node
{
friend bool operator <(node n1,node n2)
{
if(n1.n!=n2.n) return n1.n<n2.n;
else return n1.cir<n2.cir;
}
int n,cir;
};
int Find1(int x)
{
return G1[x]==x?x:G1[x]=Find1(G1[x]);
}
int Find2(int x)
{
return G2[x]==x?x:G2[x]=Find2(G2[x]);
}
int main()
{
int T,i,j,n1,n2,m1,m2,a,b,p,q;
cin>>T;
for(i=1;i<=T;i++)
{
priority_queue<node> q1;
priority_queue<node> q2;
node Node;
scanf("%d %d",&n1,&m1);
for(j=1;j<=n1;j++)
{
G1[j]=j;
rank1[j]=0;
circle1[j]=0;
}
for(j=1;j<=m1;j++)
{
scanf("%d %d",&a,&b);
p=Find1(a);
q=Find1(b);
if(p==q)
{
circle1[p]=circle1[q]=1;
}
else G1[p]=q;
}
for(j=1;j<=n1;j++)
{
rank1[Find1(j)]++;
if(circle1[j]==1) circle1[Find1(j)]=1;
}
for(j=1;j<=n1;j++)
{
if(j==Find1(j))
{
Node.n=rank1[j];
if(circle1[j]==1) Node.cir=1;
else Node.cir=0;
q1.push(Node);
}
}
scanf("%d %d",&n2,&m2);
for(j=1;j<=n2;j++)
{
G2[j]=j;
rank2[j]=0;
circle2[j]=0;
}
for(j=1;j<=m2;j++)
{
scanf("%d %d",&a,&b);
p=Find2(a);
q=Find2(b);
if(p==q)
{
circle2[p]=circle2[q]=1;
}
else G2[p]=q;
}
for(j=1;j<=n2;j++)
{
rank2[Find2(j)]++;
if(circle2[j]==1) circle2[Find2(j)]=1;
}
for(j=1;j<=n2;j++)
{
if(j==Find2(j))
{
Node.n=rank2[j];
if(circle2[j]==1) Node.cir=1;
else Node.cir=0;
q2.push(Node);
}
}
printf("Case #%d: ",i);
if(q1.size()!=q2.size()) printf("NO\n");
else
{
while(!q1.empty())
{
node no1=q1.top(),no2=q2.top();
if(no1.cir==no2.cir && no1.n==no2.n)
{
q1.pop(),q2.pop();
}
else break;
}
if(q1.empty()) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
题目本身不是很难,主要是我的思路太二缺了,唉,毕竟too young too simple啊