hdu3926Hand in Hand
http://acm.hdu.edu.cn/showproblem.php?pid=3926
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
hdu3926Hand in Hand
/*题意:判断两幅图是否同构 图中即判断图中环和链的个数是否相同 环和链是否一一相对应
利用并查集 一个集合中若人数num[]和拉手对手p[]相等 则为环,num[]==p[]+1则为链*/
#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=10001;
int pre[maxn],p[maxn],num[maxn];
int find(int x)
{
int r=x;
while(pre[r]!=r)r=pre[r];
int i=x,j;
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
void join(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx!=fy)
{
pre[fx]=fy;
num[fy]+=num[fx];
num[fx]=0;
p[fy]+=p[fx]+1;
p[fx]=0;
}
else
{
p[fx]++;
}
}
int main()
{
int cas,Cas=0,a,b,n,m;
scanf("%d",&cas);
while(cas--)
{
set <int> cir,li;
cir.clear();
li.clear();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){p[i]=0,pre[i]=i;num[i]=1;}
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
join(a,b);
}
for(int i=1;i<=n;i++)
{
if(pre[i]==i)
{
if(num[i]==p[i])cir.insert(num[i]);
else li.insert(num[i]);
}
}
int numcir=cir.size(),numli=li.size();
for(int i=1;i<=n;i++){p[i]=0;pre[i]=i;num[i]=1;}
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
join(a,b);
}
for(int i=1;i<=n;i++)
{
if(pre[i]==i)
{
if(num[i]==p[i])cir.insert(num[i]);
else li.insert(num[i]);
}
}
cout<<"Case #"<<++Cas<<": ";
if(numcir==cir.size()&&numli==li.size())cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}