求图的同构
因为只有两个度,所以每个分量只可能链表或环
用并查集判断链表和环的数量以及每个链表和环上的节点个数是否相等
相等即相似,反之不相似
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#define BUG puts("HERE!")
#define IN1(A) scanf("%d", &(A))
#define IN2(A, B) scanf("%d%d", &(A), &(B))
using namespace std;
const int MAX = 1e4 + 5;
const int INF = 0x7fffff;
int f[MAX], cnt[MAX];
int Cnum1[MAX], Lnum1[MAX];
int Cnum2[MAX], Lnum2[MAX];
int Ccnt1, Lcnt1;
int Ccnt2, Lcnt2;
bool isl[MAX];
void init(int n){
for (int i = 0; i <= n; ++i){
f[i] = i;
cnt[i] = 1;
}
memset(isl, true, sizeof(isl));
}
struct _edge{
int s, t;
bool operator < (const _edge& a) const {
if(s != a.s)
return s < a.s;
return t < a.t;
}
bool operator != (const _edge& a) const {
return s != a.s || t != a.t;
}
}a[MAX], b[MAX];
int find(int x){
return x == f[x] ? x : f[x] = find(f[x]);
}
int uni(int a, int b, int& Ccnt, int* Cnum){
int fa = find(a), fb = find(b);
if(fa == fb){
Cnum[Ccnt++] = cnt[fa] + cnt[fb];
isl[fa] = false, isl[fb] = false;
return 1;
}
else
cnt[fa] += cnt[fb], f[fb] = fa;
return 0;
}
int uq(_edge* s, int m){
int cnt = 0;
for(int i = 0; i < m; ++i)
if(i == m - 1 || s[i] != s[i + 1])
s[cnt++] = s[i];
return cnt;
}
int main(int argc, char const *argv[]){
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
// freopen("out.out", "w", stdout);
#endif
int ca, n_1, m_1, n_2, m_2;
int s, t, cas = 1;
IN1(ca);
while (ca --){
Lcnt1 = 0, Lcnt2 = 0;
Ccnt1 = 0, Ccnt2 = 0;
IN2(n_1, m_1);
init(n_1);
for (int i = 0; i < m_1; ++i){
IN2(a[i].s, a[i].t);
}
sort(a, a + m_1);
for (int i = 0; i < m_1; ++i){
uni(a[i].s, a[i].t, Ccnt1, Cnum1);
}
for (int i = 1; i <= n_1; ++i){
if(isl[i] && find(i) == i)
Lnum1[Lcnt1++] = cnt[i];
}
IN2(n_2, m_2);
init(n_2);
for (int i = 0; i < m_2; ++i){
IN2(b[i].s, b[i].t);
}
sort(b, b + m_2);
for (int i = 0; i < m_2; ++i){
uni(b[i].s, b[i].t, Ccnt2, Cnum2);
}
for (int i = 1; i <= n_2; ++i){
if(isl[i] && find(i) == i)
Lnum2[Lcnt2++] = cnt[i];
}
sort(Lnum1, Lnum1 + Lcnt1);
sort(Lnum2, Lnum2 + Lcnt2);
sort(Cnum1, Cnum1 + Ccnt1);
sort(Cnum2, Cnum2 + Ccnt2);
bool flag = true;
if(Lcnt1 == Lcnt2&& Ccnt1 == Ccnt2){
for(int i = 0; i < Lcnt1; ++i)
if(Lnum1[i] != Lnum2[i]){
flag = false;
break;
}
if(flag){
for(int i = 0; i < Ccnt1; ++i)
if(Cnum1[i] != Cnum2[i]){
flag = false;
break;
}
}
else
flag = false;
}
else
flag = false;
if(flag)
printf("Case #%d: YES\n", cas++);
else
printf("Case #%d: NO\n", cas++);
}
return 0;
}