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


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