HDU 3926 图的同构

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3926

题意:给定2个顶点度最大为2的无向图。问你这2个无向图是否同构。

思路:

1.最大度为2.说明这个图可能有多个连通分量,每个连通分量要么是环,要么是链。
2.然后遍历每个连通分量,记录该连通分量的结点个数,以及该连通分量是环还是链。
3.将第一个图按照结点个数排序(若子结点个数相同,则对链先排序)
4.将第二个图按照步骤三排序
5.比较排序后,2个图是否每个元素都相等。若相等,则相似。

关于求链通分量,当然是并查集的一些基本操作了,不过合并的时候应该遵循孩子节点少的合并到孩子节点多的集合中(不然wa),然后就是排序后比较一下就可以了(因为图可能存在环,因此可以先按孩子节点的个数排,然后再按是否存在环排)

#include<time.h>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=10000+5;
int na,ma,nb,mb,t,Ca=1,FaA[MAXN],FaB[MAXN];
struct Node{
    int cnt; //连通分量的点数
    int Type; //1:是环  0:链
    Node(int a=1,int b=0):cnt(a),Type(b){};
}GroupA[MAXN],GroupB[MAXN]; //图1,图2
void Init(){ //初始化
    for(int i=0;i<MAXN;i++){
        FaA[i]=i; FaB[i]=i;
        GroupA[i].cnt=1; GroupA[i].Type=0;
        GroupB[i].cnt=1; GroupB[i].Type=0;
    }
}
int Find(int x,int *Fa){ //并查集
    return x==Fa[x]?x:Fa[x]=Find(Fa[x],Fa);
}
void Union(int x,int y,int *Fa,Node *Group){//并查集
    int rootx=Find(x,Fa);
    int rooty=Find(y,Fa);
    if(rootx==rooty){ //存在环
        Group[rootx].Type=1;
    }
    else{ //把小的合并到大的树上
        if(Group[rootx].cnt>=Group[rooty].cnt){
            Group[rootx].cnt+=Group[rooty].cnt;
            Fa[rooty]=rootx;
        }
        else{
            Group[rooty].cnt+=Group[rootx].cnt;
            Fa[rootx]=rooty;
        }
    }
}
bool cmp(Node a,Node b){ //排序函数,先按点数排,点数相同则优先排链再到环
    if(a.cnt!=b.cnt){
        return a.cnt<b.cnt;
    }
    return a.Type<b.Type;
}
bool solve(){ //比较2个图是否同构
    sort(GroupA,GroupA+na+1,cmp);
    sort(GroupB,GroupB+nb+1,cmp);
    for(int i=0;i<=na;i++){
        if((GroupA[i].Type!=GroupB[i].Type)||(GroupA[i].cnt!=GroupB[i].cnt)){
            return false;
        }
    }
    return true;
}
int main()
{
    scanf("%d",&t);
    while(t--){
        Init();
        scanf("%d %d",&na,&ma);
        for(int i=1;i<=ma;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            Union(u,v,FaA,GroupA);
        }
        scanf("%d %d",&nb,&mb);
        for(int i=1;i<=mb;i++){
            int u,v;
            scanf("%d %d",&u,&v);
            Union(u,v,FaB,GroupB);
        }
        printf("Case #%d: ",Ca++);
        if((na!=nb)||(ma!=mb)){ //点数/边数不匹配
            printf("NO\n");
            continue;
        }
        if(solve()){
            printf("YES\n");
        }
        else{
            printf("NO\n");
        }
    }
    return 0;
}
时间: 2024-10-12 14:19:53

HDU 3926 图的同构的相关文章

hdu 3926 Hand in Hand 同构图

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3926 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 p

hdu 3926 hands in hands

https://vjudge.net/problem/HDU-3926 题意:有n个小朋友,他们之间手拉手,但是一只手只能拉一只手或者不拉,现在给出两个图,表示拉手关系,问这两个图是否同构.思路:一开始被同构难住了,后来思考发现,每一个联通分量只能是一条链或者一个简单的环,这样就比较好判断了.利用并查集统计每一个连通分量中的点,然后判断类型,判断类型的时候用度数是否为1来判断是否为链,然后将每一个连通分量先根据大小,再根据类型进行排序,最后把两个图进行一个比较即可. 1 #include <st

图论 500题——主要为hdu/poj/zoj

转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并查集======================================[HDU]1213   How Many Tables   基础并查集★1272   小希的迷宫   基础并查集★1325&&poj1308  Is It A Tree?   基础并查集★1856   More i

hdu图论题目分类

=============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many Tables 基础并查集★ 1272 小希的迷宫 基础并查集★ 1325&&poj1308 Is It A Tree? 基础并查集★ 1856 More is better 基础并查集★ 1102 Constructing Roads 基础最小生成树★ 1232 畅通工程 基础并查集★ 123

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往

[hdu 2102]bfs+注意INF

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2102 感觉这个题非常水,结果一直WA,最后发现居然是0x3f3f3f3f不够大导致的--把INF改成INF+INF就过了. #include<bits/stdc++.h> using namespace std; bool vis[2][15][15]; char s[2][15][15]; const int INF=0x3f3f3f3f; const int fx[]={0,0,1,-1};

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是