【图的同构识别】算法设计与分析实验2

 计算机科学与工程学院实验报告

课程名称

算法设计与分析

班级

实验内容

实验2:图的同构识别

指导教师

姓名

重剑DS

学号

实验日期

2022.05.19

一、问题描述,含输入、输出数据内容、格式

前言:

在Wikipedia(维基百科)上是这么描述同构的:同构是在数学对象之间定义的一类映射,它能揭示出在这些对象的属性或者操作之间存在的关系。若这两个数学结构之间存在同构映射,那么这两个结构叫做是同构的。一般来说,如果忽略掉同构的对象的属性或操作的具体定义,单从结构上讲,同构的对象是完全等价的。

使用图论中的术语来描述的话:假设G=(V,E)和G1=(V1,E1)是两个图,如果存在一个双射m:V→V1,使得对所有的x,y∈V均有xy∈E等价于m(x)m(y)∈E1,则称G和G1是同构的。这样的一个映射m称之为一个同构,如果G=G1,则称他为一个自同构(isomorphism)。在同构意义下封闭的图族叫做图性质。[1]

同构图形,是指将两个或两个以上的图形通过图形设计的组合、嫁接等处理手段组合在一起,共同构成一个新图形,并且要传达出一个新的意义。这个新图形并不是原图形的简单相加,而是一种图形意义的超越或突变,从而形成强烈的视觉冲击力。[2]

问题描述:

图的同构识别问题。给定两个无向图的顶点和顶点间的联系,判断两个图是否同构,如果是输出“Yes”,否则输出“No”。

    输入数据格式:

    第1行有2个正整数n,m,表示给定的图G1有n个顶点以及G2有m个结点。顶点编号为1,2,…,n。接下来分别给出图G1的n×n的邻接矩阵以及图G2的m×m的邻接矩阵。

【输入样例】

6 6

0 1 0 0 0 0

1 0 1 0 0 0

0 1 0 1 0 0

0 0 1 0 1 1

0 0 0 1 0 0

0 0 0 1 0 0

0 1 0 0 0 0

1 0 1 0 0 1

0 1 0 1 0 0

0 0 1 0 1 0

0 0 0 1 0 0

0 1 0 0 0 0

输出数据格式:

    程序运行结束时,将计算出的结果输出。两图同构则输出”Yes”,不同构则输出”No”。

【输出样例】

Yes

二、调试环境介绍

IDE:Dev-C++ 5.4.0

编程语言:C++

调试数据及结果(包含指定的调试数据及结果),有调试界面截图

调试的输入数据:

6 6

0 1 0 0 0 0

1 0 1 0 0 0

0 1 0 1 0 0

0 0 1 0 1 1

0 0 0 1 0 0

0 0 0 1 0 0

0 1 0 0 0 0

1 0 1 0 0 1

0 1 0 1 0 0

0 0 1 0 1 0

0 0 0 1 0 0

0 1 0 0 0 0

使用python,借助matplotlib画出对应上面输入的邻接矩阵的图1和图2,如下图所示:

图1

图2

由上面可视化后的图像不难看出两图是同构的。

上机输入效果界面截图:

运行结果:

最终运行界面截图:

中间运行过程debug调试截图:

由上图可以看到,f为true,说明此时的排列所构成的temp邻接矩阵和图2的邻接矩阵并不相等

四、算法流程图、算法的时间复杂度和空间复杂度

算法流程图如下图所示:

算法的时间复杂度如下:

根据图同构的必要非充分条件:

  • 结点数目相同 ②边数相同 ③度数相同的结点数相同。

在本代码中,最好情况下时间复杂度:当两图结点个数不同时,直接输出两图非同构,

所以最好情况时间复杂度为O(1)。

平均或最坏时间复杂度:时间复杂度主要来源于全排列的代码,产生图1结点的全部排列序列的量级是n!。在n!循环内又有两次n2的for循环,故时间复杂度为O(n2×n!)。

算法空间复杂度分析如下:

    算法的空间复杂度主要来自用于存图的邻接矩阵

其大小和问题所提供的图的节点数n和m有关,所以空间复杂度S(n)=O(max(n2, m2))。

  1. 实验中遇到的问题及解决方案(10-50字)

在实验过程中,使用vector动态生成二维数组时,奇怪为什么用上面的输入样例程序会崩溃,如下图所示

后面发现是数组大小开小了。 错误如下图所示:

因为结点序号是从1开始的,然而数组下标是从0开始,故需要数组需要多开一维即可。改成之后如下图所示:

六、参考文献(2-5个)

[1] Reinhard Diestel.图论:施普林格出版社,中文版为高等教育出版社,2013.1

[2] 潘杨,谷莉,韩君主编.图形创意:北京工业大学出版社,2012.08

附:详细代码

#include <iostream>

#include <cstring>

#include <algorithm>

#include <vector>

using namespace std;

const int N = 10;

int n, m;

int a[N];



int main()

{

  cin >> n >> m; //输入图1、2的结点数

 

  if (n != m) {

      cout << "No";

      return 0;

  }



  //根据结点数n、m,动态生成两个二维数组来存图(使用邻接矩阵的方式)

  vector<int> w1(n+1, 0);

  vector<vector<int> > g1(n+1, w1);

  vector<int> w2(m+1, 0);

  vector<vector<int> > g2(m+1, w2);



  for (int i = 1; i <= n; i ++ )  a[i] = i; //初始化a数组

 

  for (int i = 1; i <= n; i++) //输入图1的邻接矩阵

      for (int j = 1; j <= n; j++)

          cin >> g1[i][j];

 

  for (int i = 1; i <= m; i++) //输入图2的邻接矩阵

      for (int j = 1; j <= m; j++)

          cin >> g2[i][j];

 

  //全排列

  do {

      bool f = 0;

      int temp[N][N];

      memset(temp, 0, sizeof temp);

     

      for (int i = 1; i <= n; i ++)

      {

          for (int j = 1; j <= n; j ++ )

          {

             

              temp[i][j] = g1[a[i]][a[j]];

          }

      }

     

      for (int i = 1; i <= n; i ++ )

      {

          for (int j = 1; j <= n; j ++ )

          {

              if (temp[i][j] != g2[i][j] )

              {

                 f = 1;

                 break;

              }

          }

          if (f == 1) break;

      }

     

      if (f == 0)

      {

          cout << "Yes" << endl;

          return 0;

      }

  } while (next_permutation(a + 1, a + 1 + n));

 

  cout << "No" << endl;

 

  return 0;

}



/*

6 6



0 1 0 0 0 0

1 0 1 0 0 0

0 1 0 1 0 0

0 0 1 0 1 1

0 0 0 1 0 0

0 0 0 1 0 0



0 1 0 0 0 0

1 0 1 0 0 1

0 1 0 1 0 0

0 0 1 0 1 0

0 0 0 1 0 0

0 1 0 0 0 0

*/
画图用的python代码

import networkx as nx

import matplotlib.pyplot as plt



def adMmatrix2Img(matrix):

    G = nx.Graph()

    n = len(matrix)

    point = []

    for i in range(n):

        point.append(i)

    G.add_nodes_from(point)

    edglist = []

    for i in range(n):

        for k in range(i + 1, n):

            if matrix[i][k] > 0:

                edglist.append((i, k))

    G.add_edges_from(edglist)

    position = nx.circular_layout(G)

    nx.draw_networkx_nodes(G, position, nodelist=point, node_color="y")

    nx.draw_networkx_edges(G, position)

    nx.draw_networkx_labels(G, position)

    plt.show()





if __name__ == '__main__':

    # matrix = [[0,1,0,0,0,0],

    #           [1,0,1,0,0,0],

    #           [0,1,0,1,0,0],

    #           [0,0,1,0,1,1],

    #           [0,0,0,1,0,0],

    #           [0,0,0,1,0,0]

    #           ]

    matrix = [[0, 1, 0, 0, 0, 0],

              [1, 0, 1, 0, 0, 1],

              [0, 1, 0, 1, 0, 0],

              [0, 0, 1, 0, 1, 0],

              [0, 0, 0, 1, 0, 0],

              [0, 1, 0, 0, 0, 0]

              ]

    adMmatrix2Img(matrix)

  • 10
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重剑DS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值