题意:
给你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;
}