zoukankan      html  css  js  c++  java
  • 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
    ");
                continue;
            }
            if(solve()){
                printf("YES
    ");
            }
            else{
                printf("NO
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    HDOJ 2095 find your present (2)
    HDOJ 2186 悼念512汶川大地震遇难同胞——一定要记住我爱你
    九度 1337 寻找最长合法括号序列
    九度 1357 疯狂地Jobdu序列
    HDOJ 1280 前m大的数
    九度 1343 城际公路网
    九度 1347 孤岛连通工程
    HDOJ 2151 Worm
    九度 1342 寻找最长合法括号序列II
    九度 1346 会员积分排序
  • 原文地址:https://www.cnblogs.com/kirito520/p/5659214.html
Copyright © 2011-2022 走看看