題意:
給你n個小朋友,和m個操作。
操作就是讓兩個小朋友手牽手。
然後再給n給小朋友,和m個操作。問:他們組成的結構是一樣的嗎。結構的形狀有兩種,圈和鏈。我們需要注意的是,判斷他們的結構是否相同,我們可以判斷的條件有,結構的類型,圈和鏈就不一樣。然後是大小,這個可以根據人數來判斷。
這個題可以用並查集來實現。如果他們之間產生了相同的祖先,那麼他們形成了圈(注意,只有兩種形狀)。人數就好判斷多了,每一次記合併,更新根節點的狀態。
好,那麼我們把兩種的結構的狀態(人數,和形狀),都進行有序排序,那麼他們就可以對應起來,如果有一個結構不一樣,那麼就NO。
其實,如果兩次的n或m不一樣,那麼我們都不用進行判斷了。人數不一樣,結構必定不同。操作數不同,結構也必定不同。但我並沒有加這個判斷。
程序魯棒性不強。對於可能產生自環這個問題,我也沒有考慮,還好沒有。
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1e4 + 5;
int par[maxn];
int Rank[maxn];//記錄此集合的人數
bool is_circle[maxn];//判斷這個集合是否是圈
struct node
{
bool iscircle;
int R;
bool operator < (const node& a) const
{
if(R != a.R) return R < a.R;
else
{
return iscircle < a.iscircle;
}
}
}Line1[maxn], Line2[maxn];
void init(int n)
{
for(int i = 0; i <= n; i++)
{
is_circle[i] = 0;
par[i] = i;
Rank[i] = 1;
}
}
int root(int x)
{
if(x != par[x])
par[x] = root(par[x]);
return par[x];
}
void unite(int x, int y)
{
int fx = root(x);
int fy = root(y);
if(fx == fy)
{
is_circle[fx] = 1;
return;
}
par[fx] = fy;
Rank[fy] += Rank[fx];
}
bool same(int x, int y)
{
return root(x) == root(y);
}
void play(int n, int m)
{
init(n);
for(int i = 0; i < m; i++)
{
int t1, t2;
scanf("%d%d", &t1, &t2);
unite(t1, t2);
}
}
int main()
{
int T;
scanf("%d", &T);
for(int kase = 1; kase <= T; kase++)
{
int n1, m1, n2, m2;
bool flag = true;
scanf("%d%d", &n1, &m1);
play(n1, m1);
int cnt1 = 0, cnt2 = 0;
for(int i = 1; i <= n1; i++)
{
if(i == root(i))//判斷是否爲根節點
{
Line1[cnt1].R = Rank[i];
Line1[cnt1++].iscircle = is_circle[i];
}
}
scanf("%d%d", &n2, &m2);
play(n2, m2);
for(int i = 1; i <= n2; i++)
{
if(i == root(i))
{
Line2[cnt2].R = Rank[i];
Line2[cnt2++].iscircle = is_circle[i];
}
}
//printf("-----------\n%d %d\n-------------\n", cnt1, cnt2);
if(cnt1 != cnt2) flag = false;
if(flag)
{
sort(Line1, Line1 + cnt1);//有序排序
sort(Line2, Line2 + cnt1);
for(int i = 0; i < cnt1; i++)
{
if(Line1[i].R != Line2[i].R || Line1[i].iscircle != Line2[i].iscircle) flag = false;
//printf("-------------------\n%d %d\n-----------\n", Line1[i].R, Line2[i].R);
if(!flag) break;
}
}
printf("Case #%d: ", kase);
if(flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}