图论算法

图论算法在计算机科学中扮演着很重要的角色,它提供了对很多问题都有效的一种简单而系统的建模方式。很多问题都可以转化为图论问题,然后用图论的基本算法加以解决。这类问题算法主要包括Dijkstra,Floyd,Prim,最短路、网络流、二分图等算法。

 背景 

哥尼斯堡(KOnigsberg)七桥问题

在哥尼斯堡的一个公园里,有七座桥将河中两个岛及岛与河岸连接起来,问是否可能从这四块陆地中任一块出发,恰好通过每座桥一次,再回到起点

1736年,在经过一年的研究之后,29岁的欧拉提交了《哥尼斯堡七桥》的论文,圆满解决了这一问题,同时开创了数学新一分支---图论。

七桥问题在论文中,欧拉将七桥问题抽象出来,把每一块陆地考虑成一个点,连接两块陆地的桥以线表示。并由此得到了如图一样的几何图形。 若我们分别用A、B、C、D四个点表示为哥尼斯堡的四个区域。这样著名的“七桥问题”便转化为是否能够用一笔不重复地画出过此七条线的问题了。若可以画出来,则图形中必有终点和起点,并且起点和终点应该是同一点,由于对称性可知由B或C为起点得到的效果是一样的,若假设以A为起点和终点,则必有一离开线和对应的进入线,若我们定义进入A的线的条数为入度,离开线的条数为出度,与A有关的线的条数为A的度,则A的出度和入度是相等的,即A的度应该为偶数。即要使得从A出发有解则A的度数应该为偶数,而实际上A的度数是5为奇数,于是可知从A出发是无解的。同时若从B或D出发,由于B、D的度数分别是3、3,都是奇数,即以之为起点都是无解的。上述理由可知,对于所抽象出的数学问题是无解的,即“七桥问题”也是无解的。
由此我们得到:欧拉回路关系

(对于一个连通图,通常把从某结点出发一笔画成所经过的路线叫做欧拉路。人们又通常把一笔画成回到出发点的欧拉路叫做欧拉回路。具有欧拉回路的图叫做欧拉图。)

可知要使得一个图形可以一笔画,必须满足如下两个条件:
1. 图形必须是连通的。
2. 图中的“奇点”个数是0或2。

 引进概念 

图:

二元组G(V,E)称为图(graph)。V为顶点(vertex) 或结点(node)的集。E为图中边的集合。

•点用数字0...n-1表示

•点对(u,v)称为边(edge)或称弧
•子图(subgraph):边的子集和相关联的点集

•带权图:可以给边加权(weight),成为带权图,或加权图(weightedgraph).权通常代表费用、距离等,可以是正数,也可以是负数

•有向图:边都是单向(unidirectional)的,因此边(u,v)是有序数对.(最基本的图通常被定义为“无向图”,与之对应的则被称为“有向图”。两者的区别在于,有向图中的边是有方向性的。下图即是一个有向图,边的方向分别是:(1->2), (1-> 3), (3-> 1), (1->5), (2->3), (3->4), (3->5), (4->5), (1->6), (4->6)。

注意,图中的边(1->3)和(3->1)是不同的。有向图和无向图的许多原理和算法是相通的。)
有时用弧(arc)专指有向边

有时用弧(arc)专指有向边

•一条路径(path)是一个结点序列,路上的相邻结点在图上是邻接的
•如果结点和边都不重复出现,则称为简单路径(simplepath).如果除了起点和终点相同外没有重复顶点和边,称为圈(cycle).
•不相交路(disjoint path)表示没有除了起点和终点以外的公共点的路.更严格的全图:N个顶点的图,有N(N-1)/2个节点于(u,v),若邻接则改为非邻接,若非邻接则改为邻接,得到的图原图的补图

生成树:
•树:N个点,N-1条边的连通图(无环连通图)
•生成树:包含某图G所有点的树
•一个图G是树当且仅当以下任意一个条件成立
   G有V-1条边,无圈

G有V-1条边,连通
   任意两点只有唯一的简单路径
   G连通,但任意删除一条边后不连通

 最短路问题 

对一幅图G,我们对每一条边赋权w(e),成为一个赋权图。H是G的一个子图,则W(H) = sigma(w(e)),也就是对每条边的权求和。寻找从一个点a到另一个b的一个子图,使得权和最小,即为最短路问题。

解法一:Dijkstra算法(仅适用于无负权边的情况)

把顶点集合V分成两组:•(1)S:已求出的顶点的集合(初始时只含有源点VO)•(2)V-S=T:尚未确定的顶点集合
将T中顶点按递增的次序加入到S中,保证:
•(1)从源点VO到S中其他各顶点的长度都不大于从VO到T中任何顶点的最短路径长度
•(2)每个顶点对应一个距离值
•S中顶点距离:从VO到此顶点的最短距离
•T中顶点距离:从V0到此顶点的只包括S中顶点作中间顶点的

算法图解:
不断求一个点集合中的每个点,和与他相邻点最短路的最小值。我们还是从实例出发,更容易讲解。求下面这个图从A到L的最短路。

(1)
令a1 = A(便于标记),t(a1) = 0(表示点a1到a的最短路),S={a1}(被选择的点的集合),T = 0(空集 表示被选择的最短路的边集)。

(2)
求与S中的点a1与他相邻的点的距离d,取点a2 = C使得距离最小。令S={a1,a2},T={AC}。

(3)
重复第二步,求S中的点a1,a2的相邻点中(去除已选择点),距离最小的那个,则为AB,CE。再取AB,CE中权和最小的一个,B,所以a3=B,令S={a1,a2,a3},T={AC,AB}。

持续下去,不断寻找,S集合中的每个点与他相邻点的最小距离,然后在这些最小距离中找到最小的那个加入到S中,同时加入相应的边。

直到到达终点L为止。最后得到的最短路为:

此算法是多项式时间可求解的。

解法二:Floyd算法(插点法)
Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题。

算法思想原理:
Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释。从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。
算法描述:
暑假,小哼准备去一些城市旅游。有些城市之间有公路,有些城市之间则没有,如左图。为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程。

上图中有4个城市8条公路,公路上的数字表示这条公路的长短。请注意这些公路是单向的。我们现在需要求任意两个城市之间的最短路程,也就是求任意两个点之间的最短路径。我们可以用一个4*4的矩阵(二维数组e)来存储。比如1号城市到2号城市的路程为2,则设e[1][2]的值为2。2号城市无法到达4号城市,则设置e[2][4]的值为∞。另外此处约定一个城市自己到自己的路程也是0,例如e[1][1]为0。

如果求任意两点之间的最短路径,两点之间可以直接到达但却不是最短的路径,要让任意两点(例如从顶点a点到顶点b)之间的路程变短,只能引入第三个点(顶点k),并通过这个顶点k中转即a->k->b,才可能缩短原来从顶点a点到顶点b的路程。每个顶点都有可能使得另外两个顶点之间的路程变短。

当任意两点之间不允许经过第三个点时,这些城市之间最短路程就是初始路程。

在只允许经过1号顶点的情况下,任意两点之间的最短路程更新为:

在只允许经过1号顶点的情况下,只需判断e[i][1]+e[1][j]是否比e[i][j]要小即可。e[i][j]表示的是从i号顶点到j号顶点之间的路程。e[i][1]+e[1][j]表示的是从i号顶点先到1号顶点,再从1号顶点到j号顶点的路程之和。其中i是1~n循环,j也是1~n循环接下来继续求在只允许经过1和2号两个顶点的情况下任意两点之间的最短路程。

我们需要在只允许经过1号顶点时任意两点的最短路程的结果下,再判断如果经过2号顶点是否可以使得i号顶点到j号顶点之间的路程变得更短。即判断e[i][2]+e[2][j]是否比e[i][j]要小,在只允许经过1和2号顶点的情况下,任意两点之间的最短路程更新为:

判断e[i][2]+e[2][j]是否比e[i][j]要小。同理,继续在只允许经过1、2和3号顶点进行中转的情况下,求任意两点之间的最短路程。任意两点之间的最短路程更新为:

最后允许通过所有顶点作为中转,任意两点之间最终的最短路程为:

 最小生成树问题 

同样在一个连通赋权图中,寻找一颗生成树使得权和最小。

Kruskal算法(避圈法):
(1)在G中选取最小权边e,并置边数i=1;
(2)当i=n-1时结束,否则转向(3);
(3设已选择的边为e,e2,.,e,在G中选不同于e,e2,.,e的边e;+1,使得e;+是满足与e,e,...,e不构成回路且权值最小的边
(4)置为i+1,转向(2)。
不断寻找最小权的边即可。
比如,寻找下图的最小生成树

结果如下

 网络流问题 

如下图所示,有一个顶点,称为源点(source);还有一个顶点,称为汇点(sink)。对于顶点,它最大流出2,因此它的最大流入为2,如下右图所示。而他的最大流也就是5。

要想计算最大流,同样可是使用前面的思想——分阶段进行。令开始时所有边都没有流,如下中间图所示。我们可以用残余图(residual graph)来表示对于每条边还能再添加上多少流。对于每一条边,可以从容量中减去当前的流而计算出残留的流。

第一步:假设我们选择路径,此时会发出2个单位的流通过这条路径的每一边,如下中间图所示。对比左图,我们做如下约定:一旦注满(使饱和)一条边,例如到和到,就将这条边从残余图(也就是中间图)去掉,如下右图所示。

第二步:接下来选择路径,此时也会发出2个单位的流通过这条路径的每一边,如下中间图所示。同样将残余图更新如下右图所示。

第三步:从上图的残余图中我们已经可以看出来最后一步的唯一一种走法了。

做如下图所示更新。

很显然无法走到,因此算法至此便终止了。因此正好5个单位的流是最大值。

如果一开始我们选择了如下图中间所示的走法,那么算法就会失败了,因为路已经被堵死了。

为了使算法得以成功运作,那么就要让流图中具有以相反方向发送流的路径,如下所示。那么对于如下右图中的残余图而言,从d返回到a的便成了3而非4,这是因为从t流到d的流量是3个单位。现在在残余图中就有a和d之间有2个方向,或者还有1个单位的流可以从导向,或者是3个单位的流导向相反的反向,当然,我们也可以撤销流。

紧接着如果通过到导入2个单位的流,算法就会从边取走2个单位的流,更新流图如下。

参考:

1.《数据结构》、《离散数学》、《算法导论》、《挑战程序设计竞赛》等书籍和必应、维基百科等网络。
2.https://blog.csdn.net/u012469987/article/details/51319574
3.https://www.cnblogs.com/hxsyl/p/3270401.html
4.https://wk.baidu.com/view/343fcfe8172ded630b1cb6f9
5.https://wk.baidu.com/view/be1b0a7f58cfa1c7aa00b52acfc789eb172d9e07

warshall算法求传递闭包c++_【建模小课堂】图论算法相关推荐

  1. C语言用warshall算法求传递闭包transitive closure(附完整源码)

    用warshall算法求传递闭包transitive closure warshall算法求传递闭包完整源码 warshall算法求传递闭包完整源码 #include <stdbool.h> ...

  2. python决策树代码解读_建模分析之机器学习算法(附pythonR代码)

    0序 随着移动互联和大数据的拓展越发觉得算法以及模型在设计和开发中的重要性.不管是现在接触比较多的安全产品还是大互联网公司经常提到的人工智能产品(甚至人类2045的的智能拐点时代).都基于算法及建模来 ...

  3. AOJ GRL_1_C: All Pairs Shortest Path (Floyd-Warshall算法求任意两点间的最短路径)(Bellman-Ford算法判断负圈)

    题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_C All Pairs Shortest Path Input ...

  4. 蚁群算法求最值c语言实现,蚁群算法代码(求函数最值)

    <蚁群算法代码(求函数最值)>由会员分享,可在线阅读,更多相关<蚁群算法代码(求函数最值)(4页珍藏版)>请在人人文库网上搜索. 1.function F=F(x1,x2) % ...

  5. 用python做算法需要哪些技能_成为一名CV算法工程师,你需要具备哪些能力?

    算法工程师应该是这两年国内外最热门的IT岗位了. 在2019年,阿里,字节跳动(抖音)等大厂的校招社招中,开出的offer及待遇可真的是一骑绝尘啊,校招就送股票,随随便便就年薪百万. 在国内,工作经验 ...

  6. 蚁群算法求函数最值c语言,蚁群算法代码(求函数最值)

    蚁群算法简单应用 function [F]=F(x1,x2) %目标函数 F=-(x1.^2+2*x2.^2-0.3*cos(3*pi*x1)-0.4*cos(4*pi*x2)+0.7); End f ...

  7. gs地图开发_地图编制小课堂 | 境界分类

    之前我们学习了海洋.陆地等要素在地图上的表示,今天我们一起学习地图上另一重要要素--境界. 境界是一种区域范围与另一种区域范围的分界线,它是普通地图上的重要要素之一. 普通地图上,境界分为两大类:政区 ...

  8. WarShall算法求传递闭包(可达矩阵)

    最近在复习离散数学,顺便记录记录自己对warshall算法的理解. 1.传递闭包(可达矩阵) 传递闭包是有向图的一个重要性质,它指的是在有向图中从任意一个节点出发,可以到达的所有节点的集合.在某些应用 ...

  9. 动态规划 - Floyd算法求最短路径 - (Matlab建模)

    Floyd算法又称为弗洛伊德算法.插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似.该算法名称以创始人之一.1978年图灵奖获得者.斯坦福大学计算 ...

最新文章

  1. Spring boot优点
  2. 【BZOJ2558】Count on a tree
  3. SpringBoot集成多数据源
  4. django+asyncio资料调研整合
  5. 使用React Native和Spring Boot构建一个移动应用
  6. python三引号解析_[宜配屋]听图阁
  7. 使用JAVA爬取网页图片
  8. Oracle网格控制器OMA端安装Yast
  9. linux apache + mysql +php no-yum
  10. camera hardware module
  11. linux全自动备份网站到百度云盘,Linux定时备份数据到百度云盘
  12. 一打卡作弊软件CEO被判5年6个月,网友:这也太...
  13. 用php做动态时钟,时钟转动动图 如何制作转动的钟表动画?怎么做出时钟转动效果?时钟走动的动态图...
  14. html设置尖角,CSS为div添加尖角样式
  15. 易语言html加密解密,易语言实现-JScript.Encode加密解密(一)
  16. tensor如何实现转置_转置()TensorFlow中的函数
  17. 新浪体育——篮球足球的直播和战报爬取
  18. 9.高性能计算 期末复习
  19. Windows10 安装spyder3
  20. 关键元器件选型设计指引--多端口RJ45及网络变压器

热门文章

  1. linux下添加apt-get命令,Ubuntu Linux系统下apt-get命令整理
  2. 罗宾斯管理学13版pdf_全球著名管理学家,曾任五大高校教授,罗宾斯教你如何做好管理者...
  3. k1658停运_最新通知!福州这些列车停运!
  4. mysql四种隔离级别知乎_详解MySQL事务的四大特性和隔离级别
  5. Win10乱码了怎么解决 Win10系统乱码解决办法
  6. 如何在Windows11和Windows10上获取驱动程序更新
  7. 搜狐视频怎么更改头像
  8. Java重写equals方法时为什么要重写hashCode方法
  9. postman插件下载、安装教程
  10. Java基础篇1——变量与数据类型