hdu 3926

题意:

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章