49-从哥尼斯堡七桥问题开始

  关于前面的树的学习已经告一段落了,从这一篇起我们要开始新的篇章——开始图的学习,但在正式学习图之前,我们先来了解一个有趣的,关于图的问题:哥尼斯堡七桥问题。

1. 哥尼斯堡七桥问题

这里写图片描述
图1

  在18世纪初普鲁士的哥尼斯堡小镇上有一条河穿过,河上有两个小岛,有七座桥把两个岛与河岸联系起来。

  于是有人提出问题:一个步行者怎样才能不重复,不遗漏地一次走完七座桥,最后回到出发点 。

  这个问题提出后,引发了很多人的兴趣,于是小镇上的居民开始思考这个问题,进行试验,但是在之后很长的一段时间里,这个问题一直都没有得到解决。

  其实对于这个问题,利用普通数学知识,每座桥均走一次,那这七座桥所有的走法一共有5040种,如果每种走法都走一遍的话需要花费很长时间,但怎么才能找到成功走过每座桥而不重复的路线呢?因而形成了著名的“哥尼斯堡七桥问题”。

  于是就有学生给天才数学家欧拉写信,请他帮忙解决这一问题。1736年,在经过一年的研究之后,29岁的欧拉提交了《哥尼斯堡七桥》的论文,圆满解决了这一问题,同时开创了数学新一分支 ——— 图论(图论不光有在计算机中应用,而且在其他学科中也有着广泛的应用,向伟大的欧拉数学家致敬!)。


2. 欧拉解题路线

这里写图片描述
图2

  欧拉将哥尼斯堡七桥问题抽象出来,把每一块陆地考虑成一个点,连接两块陆地的桥以线表示,用A、B、C、D四个点表示为哥尼斯堡的四个区域,并由此得到了如图一样的几何图形,然后再进行形式化定义。



  欧拉在根据上面的几何图形的图性质,解决哥尼斯堡七桥问题的结论是这样的: 如果通奇数桥(七座桥是奇数桥)的地方多于两个,则不存在欧拉回路; 如果只有两个地方通奇数桥,可以从这两个地方之一出发,找到欧拉回路;如果没有一个地方通奇数桥,则无论从哪里出发,都能找到欧拉回路。结论:通奇数桥的地方为0个或2个,有欧拉回路

  比如在上图中连接A的路线有5条,连接B的路线有3条,连接C和D的路线也有3条。所以通奇数桥的地方不是0个,也不是2个,是没有欧拉回路的,因此欧拉根据这样的性质得出:没有任何一种走法可以从某地出发,不遗漏地一次走完七座桥,再回到原点。也就是说,这个问题无解。


3. 用计算机求解图问题

  其实对于哥尼斯堡七桥问题,我们可以依次计算图中与每个节点相关联的边的个数(节点的度),根据度为奇数的节点个数判定是否存在欧拉回路。

数据表示——数据结构:
  设邻接矩阵arc[n][n]这样的存储结构来描述图中每个点的桥的个数(边的个数)

这里写图片描述
图3

在邻接矩阵中:

第1行第1列的0代表A到A的边的个数为0
第1行第2列的2代表A到B的边的个数为2
第1行第3列的2代表A到C的边的个数为2
第1行第4列的1代表A到D的边的个数为1
第2行第1列的2代表B到A的边的个数为2
第2行第2列的0代表B到B的边的个数为0
第2行第3列的0代表B到C的边的个数为0
第2行第4列的1代表B到D的边的个数为1
第三行,以此类推……
第四行,以此类推……

数据处理——算法:
1. 通奇数桥的顶点个数count初始化为0;
2. 下标 i 从0 ~ n – 1重复执行下述操作:
  2.1 计算矩阵arc[n][n]第i行元素之和degree;
  2.2 如果degree为奇数,则count++;
3. 如果count等于0或2,则存在欧拉回路;否则不存在欧拉回路;



算法实现:

int main(void)
{
    //邻接矩阵arc
    char ch = 'A';
    int arc[4][4] = {               
                    {0,2,2,1},
                    {2,0,0,1},
                    {2,0,0,1},
                    {1,1,1,0}
                    };
    int count = 0;
    int i;
    int j;
    int degree = 0;

    for(i = 0; i < 4; i++)
    {
        //计算矩阵arc[n][n]第i行元素之和degree
        for(j = 0; j < 4; j++)
        {
            degree += arc[i][j];
        }
        printf("%c点的度为:%d\n" ,  ch++, degree);

        //如果degree为奇数,则count++
        if(degree % 2 == 1)
        {
            count++;
        }
        degree = 0;
    }

    //如果count等于0或2,则存在欧拉回路;否则不存在欧拉回路
    if(count == 0 || count == 2)
    {
        printf("存在欧拉回路\n");
    }
    else
    {
        printf("不存在欧拉回路\n");
    }
    return 0;
}

测试结果:
这里写图片描述



  在这一篇中我们简单介绍了哥尼斯堡七桥问题,以及用计算机求解图问题,而这也是我们接下来要学习的数据结构——图。

猜你喜欢

转载自blog.csdn.net/qq_35733751/article/details/81019337