传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3926
这题实际上是简化了很多的。。。一开始不明白图的同构是什么,想着大概两个图长得一样应该就算同构了。
思路:因为一个人只有两只手。所以一群人拉手的话,要么形成一个头尾相接的环,要么是一条链,不会有其他情况了。所以在输入的时候用并查集判断一下当前这个联通块是环还是链,再维护一下块的大小,然后把每个联通块的人数push_back到两个vector里,sort一下,判断两个图的环的个数和环的大小以及链的个数和链的大小是否相等就好了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <ctime>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
#define PB push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define calm (l+r)>>1
const int INF=1e9+7;
const int maxn=10000;
int pre[maxn+10];
bool circle[maxn+10];
int find(int x){
int s;
for(s=x;pre[s]>=0;s=pre[s]);
while(s!=x){
int t=pre[x];pre[x]=s;x=t;
}
return s;
}
void join(int a,int b){
a=find(a);b=find(b);
if(a==b){
circle[a]=true;return;
}
int sum=pre[a]+pre[b];
if(pre[a]>pre[b]){
pre[a]=b;pre[b]=sum;
}
else{
pre[b]=a;pre[a]=sum;
}
}
int n,m;
vector<int> cir[2],line[2];
bool judge(){
if(cir[0].size()!=cir[1].size()||line[0].size()!=line[1].size())return false;
sort(cir[0].begin(),cir[0].end());
sort(cir[1].begin(),cir[1].end());
sort(line[0].begin(),line[0].end());
sort(line[1].begin(),line[1].end());
for(int i=0,len=cir[0].size();i<len;i++){
if(cir[0][i]!=cir[1][i])return false;
}
for(int i=0,len=line[0].size();i<len;i++){
if(line[0][i]!=line[1][i])return false;
}
return true;
}
int main(){
//freopen("D://input.txt","r",stdin);
int T;scanf("%d",&T);
int kase=1;
while(T--){
memset(pre,-1,sizeof pre);
memset(circle,false,sizeof circle);
cir[0].clear();cir[1].clear();
line[0].clear();line[1].clear();
scanf("%d%d",&n,&m);
while(m--){
int a,b;scanf("%d%d",&a,&b);
join(a,b);
}
for(int i=1;i<=n;i++){
if(pre[i]<0){
if(circle[i]){
cir[0].PB(-pre[i]);
}
else{
line[0].PB(-pre[i]);
}
}
}
memset(pre,-1,sizeof pre);
memset(circle,false,sizeof circle);
scanf("%d%d",&n,&m);
while(m--){
int a,b;scanf("%d%d",&a,&b);
join(a,b);
}
for(int i=1;i<=n;i++){
if(pre[i]<0){
if(circle[i]){
cir[1].PB(-pre[i]);
}
else{
line[1].PB(-pre[i]);
}
}
}
if(judge()){
printf("Case #%d: YES\n",kase++);
}
else printf("Case #%d: NO\n",kase++);
}
return 0;
}