HDU3926Hand 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

Source

2011 Multi-University Training Contest 9 - Host by BJTU

搜索:

#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;

const int N = 10100;
struct node
{
    int sum,cyc;
};

node sta1[N],sta2[N];
int vist[N];
vector<int>tmap[N];

bool cmp(const node &g1, const node &g2)
{
    if(g1.sum < g2.sum)
        return true;
    else if(g1.sum == g2.sum && g1.cyc < g2.cyc)
        return true;
    else
        return false;
}

void addedg(int a,int b)
{
    int flag=0;
    for(int i=0;i<tmap[a].size();i++)
        if(b==tmap[a][i])
    {
        flag=1; break;
    }
    if(flag==0)
        tmap[a].push_back(b),tmap[b].push_back(a);
}
void init(int n)
{
    for(int i=0;i<=n;i++)
        {
            vist[i]=0; tmap[i].clear();
        }
}
void DFS(int x,int fath,node &ss)
{
    ss.sum++; vist[x]=1;
    for(int i=0;i<tmap[x].size();i++)
    {
        if(fath==tmap[x][i])continue;
        if(vist[tmap[x][i]])
        {
            ss.cyc=1; continue;
        }
        DFS(tmap[x][i],x,ss);
    }
}

int main()
{
    int t,a,b,n[2],m[2],c=0,flag;
    scanf("%d",&t);
    while(t--)
    {
        c++; flag=1;
        scanf("%d%d",&n[0],&m[0]);

        init(n[0]);
        for(int i=1;i<=m[0];i++)
        {
            scanf("%d%d",&a,&b);
            addedg(a,b);
        }

        int k1=0;
        for(int i=1;i<=n[0];i++)
        if(vist[i]==0)
        {
            sta1[k1].cyc=sta1[k1].sum=0;
            DFS(i,-1,sta1[k1]);
            k1++;
        }

        scanf("%d%d",&n[1],&m[1]);
        if(n[1]!=n[0])
            flag=0;
        init(n[1]);
        for(int i=1;i<=m[1];i++)
        {
            scanf("%d%d",&a,&b);
            if(flag)
            addedg(a,b);
        }
        if(flag)
        {
            int k2=0;
            for(int i=1;i<=n[1];i++)
            if(vist[i]==0)
            {
                sta2[k2].cyc=sta2[k2].sum=0;
               DFS(i,-1,sta2[k2]); k2++;
            }

            if(k1!=k2)
            flag=0;

            sort(sta1,sta1+k1,cmp);
            sort(sta2,sta2+k2,cmp);
            for(int i=0;i<k1;i++)
            if(sta1[i].sum!=sta2[i].sum||sta1[i].cyc!=sta2[i].cyc)
            {
                flag=0; break;
            }
        }
        if(flag)
            printf("Case #%d: YES\n",c);
        else
            printf("Case #%d: NO\n",c);
    }
}

并查集:
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;

const int N = 10100;
struct node
{
    int sum,cyc;
};

node sta1[N],sta2[N];
int fath[N],cyc[N],sum[N];

bool cmp(const node &g1, const node &g2)
{
    if(g1.sum < g2.sum)
        return true;
    else if(g1.sum == g2.sum && g1.cyc < g2.cyc)
        return true;
    else
        return false;
}

int findfath(int x)
{
    if(x==fath[x])
        return fath[x];
    fath[x]=findfath(fath[x]);
    return fath[x];
}
void setfath(int x,int y)
{
    x=findfath(x);
    y=findfath(y);
    if(x==y)
        cyc[x]=1;
    else
        fath[x]=y,sum[y]+=sum[x];
}
void init(int n)
{
    for(int i=0;i<=n;i++)
        {
            cyc[i]=0;
            sum[i]=1; fath[i]=i;
        }
}

int main()
{
    int t,a,b,n[2],m[2],c=0,flag;
    scanf("%d",&t);
    while(t--)
    {
        c++; flag=1;
        scanf("%d%d",&n[0],&m[0]);

        init(n[0]);
        for(int i=1;i<=m[0];i++)
        {
            scanf("%d%d",&a,&b);
            setfath(a,b);
        }

        int k1=0;
        for(int i=1;i<=n[0];i++)
        if(fath[i]==i)
        {
            k1++;
           sta1[k1].sum=sum[i];
           sta1[k1].cyc=cyc[i];
        }

        scanf("%d%d",&n[1],&m[1]);
        if(n[1]!=n[0])
            flag=0;
        init(n[1]);
        for(int i=1;i<=m[1];i++)
        {
            scanf("%d%d",&a,&b);
            if(flag)
            setfath(a,b);
        }
        if(flag)
        {
            int k2=0;
            for(int i=1;i<=n[1];i++)
            if(fath[i]==i)
            {
                k2++;
               sta2[k2].sum=sum[i];
               sta2[k2].cyc=cyc[i];
            }

            if(k1!=k2)
            flag=0;

            sort(sta1+1,sta1+k1+1,cmp);
            sort(sta2+1,sta2+k2+1,cmp);
            for(int i=1;i<=k1;i++)
            if(sta1[i].sum!=sta2[i].sum||sta1[i].cyc!=sta2[i].cyc)
            {
                flag=0; break;
            }
        }

        printf("Case #%d: %s\n",c,flag>0?"YES":"NO");
    }
}
时间: 2024-07-30 09:31:40

HDU3926Hand in Hand(搜索 或 并查集)的相关文章

hdu 1198 Farm Irrigation (搜索或并查集)

Farm Irrigation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5818    Accepted Submission(s): 2521 Problem Description Benny has a spacious farm land to irrigate. The farm land is a rectangle

CodeForces 510B 无向图找环的两种方法(搜索与并查集)

题目连接:http://codeforces.com/problemset/problem/510/B 解法: dfs 每次把父节点的值记录并传递下去,判断一下新达到节点: (1)没有走过 → 继续搜索: (2)走过&&不是父节点(对于本题步数也要>=4) → 找到环: 并查集 每个节点映射成 i*m+j从起点开始分别把它下面与于右面的节点加进来,如果发现有节点已经在集合中,那么环已经找到了. DFS: #include<cstdio> #include<cstdl

【搜索】【并查集】Codeforces 691D Swaps in Permutation

题目链接: http://codeforces.com/problemset/problem/691/D 题目大意: 给一个1到N的排列,M个操作(1<=N,M<=106),每个操作可以交换X Y位置上的数字,求可以得到的最大字典序的数列. 题目思路: [搜索][并查集] 这题可以用搜索或者并查集写,都能过. 把位置分成若干块,每一块里面的位置都是可以被这一块里另一个位置经过若干次调换的(类似强连通,位置可达). 然后把每一块位置里的 位置按从小到大排序,位置上的值按从大到小排序,依次填入位置

hust 1385 islands 并查集+搜索

islands Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/problem/show/1385 Description Deep in the Carribean, there is an island even stranger than the Monkey Island, dwelled by Horatio Torquemada Marley. Not only it has a rectangu

并查集的离线搜索([JSOI2008]星球大战)

很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重新造出了他的超级武器.凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球.由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来.现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次

【NOIP模拟_54测试】【并查集】【二进制】【搜索】【区间序列类】

第一题 Mushroom的序列 大意: 给一个序列,求一段连续最长区间满足:最多改变一个数,使得区间是严格的上升子序列. 解: 直接扫描一遍,记一个最长上升子序列编号.然后从每一个编号为1 的点来判断是否可以将两个序列合并,有两种情况,讨论需要注意多种子情况...我可能想的比较复杂,所以第一遍写的时候少考虑了一些相等的情况,就WA 了一个点. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #i

并查集问题hdu 1232

Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可).问最少还需要建设多少条道路? Input 测试输入包含若干测试用例.每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M:随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号.为简单起见,城镇从1

并查集 (Union-Find Sets)及其应用

定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并. 主要操作 初始化 把每个点所在集合初始化为其自身. 通常来说,这个步骤在每次使用该数据结构时只需要执行一次,无论何种实现方式,时间复杂度均为O(N). 查找 查找元素所在的集合,即根节点. 合并 将两个元素所在的集合合并为一个集合. 通常来说,合并之前,应先判断两个元素是否属于

HDU 4514 湫湫系列故事——设计风景线(并查集+树形DP)

湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 4669    Accepted Submission(s): 853 Problem Description 随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形