hdu 3926 Hand in Hand

Hand in Hand

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 122768/62768 K (Java/Others)
Total Submission(s): 871    Accepted Submission(s): 330


Problem Description
In order to get rid of Conan, Kaitou KID disguises himself as a teacher in the kindergarten. He knows kids love games and works out a new game called "hand in hand". 

Initially kids run on the playground randomly. When Kid says "stop", kids catch others' hands immediately. One hand can catch any other hand randomly. It's weird to have more than two hands get together so one hand grabs at most one other hand. After kids stop moving they form a graph.

Everybody takes a look at the graph and repeat the above steps again to form another graph. Now Kid has a question for his kids: "Are the two graph isomorphism?" 
 

Input
The first line contains a single positive integer T( T <= 100 ), indicating the number of datasets.
There are two graphs in each case, for each graph:
first line contains N( 1 <= N <= 10^4 ) and M indicating the number of kids and connections.
the next M lines each have two integers u and v indicating kid u and v are "hand in hand".
You can assume each kid only has two hands.
 

Output
For each test case: output the case number as shown and "YES" if the two graph are isomorphism or "NO" otherwise.
 

Sample Input
2 3 2 1 2 2 3 3 2 3 2 2 1 3 3 1 2 2 3 3 1 3 1 1 2
 

Sample Output
Case #1: YES Case #2: NO
题意:每个人手拉手,每个点的度最多为2,构成图中环或链,判断两个这样的图是否同构。
思路:用并查集合并,得到若干个集合,比较两个图中集合是否相同,包括集合的个数,集合中点的个数,集合中点的构成是链还是环。
AC代码:
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <cmath>
#include <vector>
#include <cstdlib>

using namespace std;
const int MAX=10005;
int fa1[MAX],fa2[MAX];
struct graph
{
    int son;         //集合中点的个数
    bool is_ring;   //是否为环的标志
}g1[MAX],g2[MAX]; 

bool cmp(graph a,graph b)     //先按集合点的个数排序,若相等,再按是否为环排序
{
    if(a.son!=b.son)
    return a.son<b.son;
    return a.is_ring<b.is_ring;
}
int Find_set(int n,int fa[])
{
    if(n!=fa[n])
    fa[n]=Find_set(fa[n],fa);
    return fa[n];
}
void Union(int a,int b,int fa[],graph g[])
{
    int ra=Find_set(a,fa);
    int rb=Find_set(b,fa);
    if(ra==rb) g[ra].is_ring=true;      //有环
    else
    {
        if(g[ra].son>=g[rb].son)
        {
            fa[rb]=ra;
            g[ra].son+=g[rb].son;
        }
        else
        {
            fa[ra]=rb;
            g[rb].son+=g[ra].son;
        }
    }
}
void init()
{
    for(int i=0; i<MAX; i++)
    {
        fa1[i]=i;
        g1[i].son=1;
        g1[i].is_ring=false;
        fa2[i]=i;
        g2[i].son=1;
        g2[i].is_ring=false;
    }
}
bool Compare(int num)
{
    sort(g1+1,g1+num+1,cmp);
    sort(g2+1,g2+num+1,cmp);
    for(int i=1;i<=num;i++)
    //若两个集合点的个数不相等,或个数相等但不同时为链或环
    if(g1[i].son!=g2[i].son||(g1[i].son==g2[i].son&&g1[i].is_ring!=g2[i].is_ring)) 
    return false;
    return true;
}
int main()
{
    int t,c=0,num,edg1,edg2,a,b;
    scanf("%d",&t);
    while(t--)
    {
        bool flag=true;
        scanf("%d%d",&num,&edg1);
        init();
        for(int i=0;i<edg1;i++)
        {
            scanf("%d%d",&a,&b);
            Union(a,b,fa1,g1);
        }
        scanf("%d%d",&num,&edg2);
        if(edg2!=edg1)
        flag=false;
        for(int i=0;i<edg2;i++)
        {
            scanf("%d%d",&a,&b);
            if(flag)
            Union(a,b,fa2,g2);
        }
        if(!flag)
        {
            printf("Case #%d: NO\n",++c);
            continue;
        }
        flag=Compare(num);

        if(flag)
        printf("Case #%d: YES\n",++c);
        else
        printf("Case #%d: NO\n",++c);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值