无向图同构 (哈希)「建议收藏」

题目ProblemDescription如果一个无向图重标号后与另一个无向图完全一致(即对于任意两点,他们之间的边在两个图中都存在或都不存在),则称两个无向图同构。给定两个n个点m条边的无向图,判定两个无向图是否同构。Input第一行一个数T,表示有T组数据(T<=20)对于每一组数据:

大家好,又见面了,我是你们的朋友全栈君。

题目

Problem Description

如果一个无向图重标号后与另一个无向图完全一致(即对于任意两点,他们之间的边在两个图中都存在或都不存在),则称两个无向图同构。

给定两个n个点m条边的无向图,判定两个无向图是否同构。

Input

第一行一个数T,表示有T组数据(T<=20)
对于每一组数据:
第一行两个数n,m,表示要判定的两个无向图都是n个点m条边(n<=200,m<=4000)
接下来m行,每行两个数x,y,表示在第一个图中存在一条边连接点x和点y(1<=x,y<=n)
接下来m行,每行两个数x,y,表示在第二个图中存在一条边连接点x和点y(1<=x,y<=n)

Output

对于每一组数据,如果两个无向图同构则输出”YES”,否则输出”NO”

Sample Input

4
5 6
1 2
1 3
1 5
4 1
2 3
5 4
3 1
5 4
3 4
2 3
3 5
1 2

5 6
1 2
1 3
1 5
4 1
2 3
5 4
3 1
5 4
3 4
2 3
3 5
1 4

3 2
1 2
2 3
2 1
1 3

4 3
1 2
2 3
3 4
1 2
1 3
1 4

Sample Output

YES
NO
YES
NO

分析

  • 看两个图是否同构,可以想到用哈希值来确定一个图。
  • 那么对于一个图,它的哈希值就应该只和它的结构有关,和点的编号无关,于是可以有下面这种哈希规则
    • 对于每个点,它的哈希值是它的权值与“和它相邻的点”的权值的和(当然可以再乘一些数再模一下)。
    • 起初全部点的权值都为 1,然后进行多次改变操作,每次中先把点按上一次的权值排个序,再按上面的规则修改哈希值即可。
    • 由于排了序,那么此图的哈希值就只会和它的结构有关了。
  • 进行多次改变后,若两个图中的点,权值情况相同,那么我们就可以看成它们同构了。(当然运气不好可能可以被卡,那就多变换几次,哈希操作也弄复杂一点吧)

程序

#include <cstdio>
#include <algorithm>
#define For(G,x) for(int h=G.head[x],o=G.V[h]; h; o=G.V[h=G.to[h]])
#define N 205
#define M 4005
using namespace std;
struct Tu{
    int head[N],to[M*2],V[M*2],num;
    void Add(int x,int y){to[++num]=head[x],head[x]=num,V[num]=y;}
}A,B;
struct zzk{
  
  int id,v;} a[2][N],b[2][N];
int n,m,cnt,k,F=1,f1[2][N],f2[2][N];
bool cmp(zzk x,zzk y){
  
  return x.v<y.v;}

void Hash(){
    sort(a[cnt]+1,a[cnt]+n+1,cmp);
    sort(b[cnt]+1,b[cnt]+n+1,cmp);
    for (int i=1,u=a[cnt][i].id; i<=n; i++,u=a[cnt][i].id){
        k=f1[cnt][u]*18;        //随意弄个规则修改 Hash 值 
        For(A,u) k+=f1[cnt][o]*666233;
        a[cnt^1][i].id=u;
        f1[cnt^1][u]=a[cnt^1][i].v=k;
    }
    for (int i=1,u=b[cnt][i].id; i<=n; i++,u=b[cnt][i].id){
        k=f2[cnt][u]*18;        //用同一个规则修改 Hash 值 
        For(B,u) k+=f2[cnt][o]*666233;
        b[cnt^1][i].id=u;
        f2[cnt^1][u]=b[cnt^1][i].v=k;
    }
    cnt^=1;
}

int main(){
    for (int T=(scanf("%d",&T),T),uu,vv; T--; F=1){

        A.num=B.num=0;
        for (int i=1; i<=n; i++) A.head[i]=B.head[i]=0;

        scanf("%d%d",&n,&m);
        for (int i=1; i<=m; i++) scanf("%d%d",&uu,&vv),A.Add(uu,vv),A.Add(vv,uu);
        for (int i=1; i<=m; i++) scanf("%d%d",&uu,&vv),B.Add(uu,vv),B.Add(vv,uu);
        for (int i=1; i<=n; i++){
            a[0][i].id=a[1][i].id=b[0][i].id=b[1][i].id=i;
            f1[cnt][i]=a[cnt][i].v=f2[cnt][i]=b[cnt][i].v=1;
        }
        for (int i=1; i<=n; i++) Hash();    //多次变换 
        sort(a[cnt]+1,a[cnt]+n+1,cmp);
        sort(b[cnt]+1,b[cnt]+n+1,cmp);
        for (int i=1; i<=n; i++)
            if (a[cnt][i].v!=b[cnt][i].v) {F=0; break;}
        puts(F?"YES":"NO");
    }
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/126321.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • vim命令大全(转)[通俗易懂]

    vim命令大全(转)[通俗易懂]命令历史以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择某个历史命令。启动vim在命令行窗口中输入以下命令即可vim直接启动vimvimfilename打开vim并创建名为filename的文件文件命令打开单个文件vimfile同时打开多个文件vimfile1file2file3…在vim窗口中打开一个…

    2022年5月30日
  • web.xml中contextConfigLocation的作用

    web.xml中contextConfigLocation的作用在web.xml中通过contextConfigLocation配置spring,contextConfigLocation参数定义了要装入的Spring配置文件。1.在web.xml里配置需要加载的spring配置文件。  如果要装入多个配置文件,在<param-value>标记中用逗号作分隔符即可。<context-param>…

    2022年6月16日
  • UFT常识

    UFT常识UFT也用了一段时间了,自己竟然还老犯同样的错误,遇到同样的问题。自己还不能单独解决,对不起导师,对不起自己。下面对UFT中的一些基本问题总结一下。1.关于DataTable导入:DataTable.ImportSheet(FileName,SheetSource,SheetDest)FileName: ThefullorrelativepathoftheExce

    2022年5月8日
  • 四角号码数字在线查询_七的四角号码

    四角号码数字在线查询_七的四角号码伟大的网络,让汉字的四角号码查询变成在线的了曾经有很多人想用四角号码,但苦于太难,基本放弃了。但至从有个四角号码查询器,和四角号码输入法,使用的人又多了起来。但始终不方便,需要安装软件。而伟大的网络,

    2022年8月4日
  • 阿里ECS云服务器买来之后必做的几个操作

    阿里ECS云服务器买来之后必做的几个操作今天我为大家带来的是如何在云服务器中配置自己的环境。在这里先说明一下我的配置,我使用的是阿里云服务器ECS+Ubuntu20.0464位来实现的,不同的服务器和不同的系统版本可能会导致操作有些许不同,如果你是华为云或者腾讯云又或者是百度云的用户,还请自己多多摸索,大致的思路是一样的。废话不多说,我们现在就开始来着手实现吧——此处我们是假设你已经购买好阿里云ECS云服务器哦!1.检查你的安全组首先,我们要做的是打开你的安全组,检查你的22端口是否被开启,只有当端口

    2022年5月4日
  • 《阿里巴巴Java开发手册》扫描插件正式发布–插件安装和使用分析

    本博文始发地址在公司论坛::《阿里巴巴Java开发手册》扫描插件正式发布–插件安装和使用分析“不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!”阿里巴巴于10月14日上午9:00在杭州云栖大会《研发效能峰会》上,正式发布《阿里巴巴Java开发手册》扫描插件。下面分享这个插件,希望更多的人使用,提高我们的代码/编码的规范!

    2022年2月26日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号