HDU3926-同构图

Hand in Hand

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


 

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

 题意:首先输入t组数据,然后输入第一个图的点数和边数n,m然后给出m条边。之后给出第二个图的点数和边数n,m然后给出m条边。问这两个图书不是同构图

思路:由于没学同构图算法,上网去找博客也没找到代码。。。所以就直接看了一下这题的代码

思路是这样的,首先图里面可能有环和链,我们先把这些分割一下,然后判断这些环和链是不是同构的。所以我们用一个结构体来储存一个环和一条链里面的点的个数,然后用一个变量来判断环和链。

AC代码:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=10000+10;
struct Node
{
    int sum;        //点的数量
    bool ck;        //属于环或链
}num1[maxn],num2[maxn];
int pre[maxn],Rank[maxn],roll[maxn];
bool cmp(const Node &a,const Node &b)
{
    if (a.sum!=b.sum)
        return a.sum<b.sum;   //这里排序是为了找出同构的环或链,通过必须点的数量相同
    if (a.ck<b.ck)      //类型也要相同
        return 1;
    return 0;
}
int find(int x)        //这里用并查集把几个点集中在一个点里面
{
    if (x==pre[x])
        return x;
    return pre[x]=find(pre[x]); 
}
void unite(int x,int y)
{
    int a=find(x);
    int b=find(y);
    if (a!=b)
        {
            pre[b]=a;
            Rank[a]=Rank[a]+Rank[b];
        }
    else roll[a]=1;     //如果两个父节点相同说明是环
    return ;
}
void Init()
{
    for (int i=0;i<maxn;i++)
        {
            pre[i]=i;
            Rank[i]=1;
        }
    memset(roll,0,sizeof(roll));
    return ;
}
int main()
{
    int t,k,i,j,x,y,n1,m1,n2,m2,sum1,sum2;
    k=1;
    cin>>t;
    while (t--)
        {
            cin>>n1>>m1;
            Init();
            for (i=1;i<=m1;i++)
                {
                    scanf("%d%d",&x,&y);
                    unite(x,y);
                }
            sum1=sum2=0;
            for (i=1;i<=n1;i++)            //把所有的父节点记录一下,父节点属于的类型也记录一下
                if (find(i)==i)
                    {
                        num1[sum1].ck=roll[i];
                        num1[sum1++].sum=Rank[i];
                    }
            cin>>n2>>m2;
            Init();
            for (i=1;i<=m2;i++)
                {
                    scanf("%d%d",&x,&y);
                    unite(x,y);
                }
            for (i=1;i<=n2;i++)
                if (find(i)==i)
                    {
                        num2[sum2].ck=roll[i];
                        num2[sum2++].sum=Rank[i];
                    }
            printf("Case #%d: ",k++);
            if (n1!=n2||m1!=m2)        //如果一开始的两个图的点或边都不一样就直接no
                {
                    cout<<"NO"<<endl;
                    continue;
                }
            if (sum1==sum2)       
                {
                    sort(num1,num1+sum1,cmp);     //这里排序是为了判断每种类型是不是相同,点数是不是相同
                    sort(num2,num2+sum2,cmp);
                    for (i=0;i<sum1;i++)
                        {
                            if (num1[i].ck!=num2[i].ck)
                                break;
                            if (num1[i].sum!=num2[i].sum)
                                break;
                        }
                    if (i==sum1)
                        cout<<"YES"<<endl;
                    else cout<<"NO"<<endl;
                }
            else cout<<"NO"<<endl;
        }
    return 0;
}
发布了46 篇原创文章 · 获赞 2 · 访问量 3217

猜你喜欢

转载自blog.csdn.net/z1164754004z/article/details/86561143