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

题目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");
    }
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 浅谈CSRF攻击方式

    浅谈CSRF攻击方式

  • numpy float转int_python字符串转float类型

    numpy float转int_python字符串转float类型查看数据类型print(image.dtype)unit8转换成float32先将图片转化为float32类型,再除以255,得到0-1之间的数importnumpyasnpimage=image.astype(np.float32)/255float32转换成uint8每个数乘以255,再转化为uint8importnumpyasnpimage=(image*255).astype(np.uint8)…

  • scope 前缀开头的方法

    scope 前缀开头的方法

  • resnet是卷积神经网络吗_神经网络架构搜索的应用

    resnet是卷积神经网络吗_神经网络架构搜索的应用卷积神经网络在图像识别方面应用广泛,在实际应用在中,识别的准确率不仅仅与数据量有关,还与模型的架构有很大的关联。从首个成功应用于数字识别的卷积神经网络LeNet,到卷积神经网络崛起点AlexNet,以及陆陆续续的ZFNet,VGGNet,Inception系列和ResNet,这些架构在网络深度,宽度,卷积核大小和可视化部分都做了很大的改进,使得卷积神经网络的性能越来越强。

  • linux下安装boost

    linux平台下要编译安装除gcc和gcc-c++之外,还需要两个开发库:bzip2-devel和python-devel,因此在安装前应该先保证这两个库已经安装:#yuminstallgcc

    2021年12月28日
  • java clone()_java throwable

    java clone()_java throwable克隆是一种基本的编程模式。事实上,Java在很多方面可能实现得很差,但这丝毫没有减少克隆的必要性。而且,很容易实现克隆,无论你希望它如何工作,浅层的,深层的,混合的,无论什么。如果愿意的话,甚至可以为函数使用clone名称,而不实现Cloneable。假设我有类A、B和C,其中B和C是从A派生的。如果我有一个A类型的对象列表,如下所示:ArrayListlist1;ArrayListlist2…

    2022年10月10日

发表回复

您的电子邮箱地址不会被公开。

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