hdu 3926 Hand in Hand

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
题意:求两个图是否同构。
探索时思路:把每个图的每个节点的度,边的总和求出,如果不一样就不同构,这是最基本的处理。 想了一下进一步的处理:把所有的连通分量按照根节点的大小排序,再将一个在同一个连通分量的所有节点按照编号的大小排序,这样把每个连通分量都按照这样的方式排序,连通分量间按照根节点排序,放到一个数组当中。最后将两个图得到的排序一一比较,若有一个不同,则不同构。
这是我没有AC的思路,度跟边好处理,就是在排序那里有问题。仔细考虑了一下,如果要这样做,那必须做到在同一个连通分量的所有节点的根节点都是一样的。而我写的Merge函数不能做到这一点。。。

问:怎样才能做到在同一个连通分量的结点其根节点都一致???

下面是我在网上学到的思路:
1.该题形成的图有多个连通分量,非链即环,且每个点的度不得大于2
2.基本的Find,merge不变,把合并好后的所有点进行排序(点的子结点数优先,从小到大排列,若子节点数相等,则链在前)
3.把两个图排序后一一比较两个点,若有一个不同,则不同构。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <algorithm>
#include <queue>
#include <stack>
#define MAXN 30005
#define MAX 10005
#define INF 0x3f3f3f3f
using namespace std;
int Father[MAX];
struct graph
{
    int num;//节点数
    bool ring;//是否是环
};
graph g1[MAX],g2[MAX];
int p,q,t,cnt,n1,m1,n2,m2,flag;
bool cmp1(const graph &a, const graph &b)//结点小的优先,链表优先
{
    if(a.num < b.num)
    {
        return true;
    }
    if(a.num == b.num && a.ring < b.ring)
    {
        return true;
    }
    return false;
}

int Find(int x)
{
    return x == Father[x]?Father[x]:Find(Father[x]);
}
void Merge(int x,int y,graph *g)
{
    int ix = Find(x);
    int iy = Find(y);
    if(ix == iy)
    {
        g[ix].ring = true;
    }
    else
    {
        if(g[ix].num > g[iy].num)
        {
            Father[iy] = ix;
            g[ix].num += g[iy].num;
        }
        else
        {
            Father[ix] = iy;
            g[iy].num += g[ix].num;
        }
    }
}

int cmp2(graph *g1, graph *g2,int len1,int len2)
{
    sort(g1+1,g1+1+len1,cmp1);
    sort(g2+1,g2+1+len2,cmp1);
    for (int i = 1; i <= len2; i++)
    {
        if(g1[i].num != g2[i].num || (g1[i].num == g2[i].num &&g1[i].ring !=g2[i].ring))
        {
            return 0;
        }
    }
    return 1;

}
void Unit(int n, int m, graph *g)
{
    for(int i = 1; i <= n; i++)
    {
        Father[i] = i;
        g[i].num = 1;
        g[i].ring = false;
    }
}
int main()
{
    scanf("%d",&t);
    while (t--)
    {
        cnt++;
        flag = 0;
        scanf("%d%d",&n1,&m1);
        Unit(n1,m1,g1);
        for (int i = 0; i < m1;i++)
        {
            scanf("%d%d",&p,&q);
            Merge(p,q,g1);
        }
        scanf("%d%d",&n2,&m2);
        Unit(n2,m2,g2);
        for (int i = 0; i < m2;i++)
        {
            scanf("%d%d",&p,&q);
            Merge(p,q,g2);
        }
        flag = cmp2(g1,g2,n1,n2);
        printf("Case #%d: ",cnt);
        if(flag)
        {
            printf("YES\n");
        }
        else
        {
            printf("NO\n");
        }
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值