北京大学ACM暑期课讲义-Bellman-ford算法培训讲学
信息学奥赛一本通 第4章 第3-4节 图论算法(C++版)
//初始化f数组为最大值
• • • • • • • • • • • • • • •
for (i = 1; i <= m; i++) //预处理出x、y间距离 { cin >> x >> y; f[y][x] = f[x][y] = sqrt(pow(double(a[x][1]-a[y][1]),2)+pow(double(a[x][2]a[y][2]),2)); //pow(x,y)表示x^y,其中x,y必须为double类型,要用cmath库 } cin >> s >> e; for (k = 1; k <= n; k++) //floyed 最短路算法 for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) if ((i != j) && (i != k) && (j != k) && (f[i][k]+f[k][j] < f[i][j])) f[i][j] = f[i][k] + f[k][j]; printf("%.2lf\n",f[s][e]); return 0; }
图1所示的牧场的直径大约是12.07106, 最远的两个牧区是A 和E,它们之间的最短路径是A-B-E。 这两个牧场都在John的 农场上。John将会在两个牧场中各选一个牧区,然后用一条路径连 起来,使得连通后这个新的更大的牧场有最小的直径。注意,如果 两条路径中途相交,我们不认为它们是连通的。只有两条路径在同 一个牧区相交,我们才认为它们是连通的。 现在请你编程找 出一条连接两个不同牧场的路径,使得连上这条路径后,这个更大 的新牧场有最小的直径。
北京大学ACM暑期课讲义-计算几何教程
解答
利用三角剖分,计算各个三角形的面积和
重心,将此三角形化为一个质量为其面积, 坐标为其重心的质点。
若此三角形属于“负部分”,则其拥有
“负质量”。
最后计算质点组的重心即可。
凸集
凸集举例
空集
直线、射线、线段
凸多边形
圆及内部、二次曲线及内部
若干种原料,每种原料含 A 成分和 B 成
水平序 Graham 扫描算法
Graham 扫描算法有水平序和极角序两种。
极角序算法能一次确定整个凸包,但是计
算极角需要用到三角函数,速度较慢,精 度较差,特殊情况较多。
水平序算法需要扫描两次,但排序简单,
讨论简单,不易出错。
算法流程
算法演示
首先将所有点排序。
算法演示
将 1 和 2 压入栈。
间复杂度是 O(N log N)。
若坐标均为整数,可以用基数排序将复杂
度优化到 O(N)。
旋转卡壳算法
如何计算 N 个点中,距离最大的两个点的
距离?
要求 O(N log N) 的算法。
容易证明距离最大的两个点一定是凸包上
的两个点,很明显是先求凸包然后做文章 啦。
对踵点
若凸包上的两个顶点能落在一对平行切线
分的比例不同;混合这些原料能得到的产 品的 A, B 两种成分的比例
ACM新生培训讲座课件
13
约瑟夫环问题二
问题描述:编号从1到n的n个人站成一个 环,从第一个人开始,每数到 m的时候, 去除该位置上的人,直到只剩下一个人, 求剩下的这个人的编号。
我们用J(n,m)表示人数为n,每次都去掉 第m个人的时候的解。
16
约瑟夫环问题三
不要妄想再找到公式了,模拟是唯一的选择, 但是直接模拟的话,该算法的复杂度将达到 O(n^2).
事实上,我们可以用线段数对此做一个优化, 用线段数来统计每个区间上还剩下人的个数, 从而使算法的复杂度降低到O(n*logn)。
线段数??一棵平衡二叉树,它的每个节点 都是一个线段,这里就不做详细介绍了。
9
约瑟夫环问题一
剩下的n个人还是一个新的约瑟夫环问题。
1 2 3 4 … n-1
n
3 5 7 9 … 2n-1 2n+1
J(2n+1)=2*J(n)-1
10
约瑟夫环问题一
综上,我们可以得到如下递推公式:
该问题可以在O(n)的复杂度解决。
11
约瑟夫环问题一
12
约瑟夫环问题一
由上图可以看出如果n为2的幂次方的时候, J(n)=1,这是显然的。而在此之后J(n)以2递增, 因此我们可以猜测:
北京大学ACM国际大学生程序设计竞赛课件4
1048 Follow My Logic
题中的逻辑电路满足以下条件:
1.逻辑电路图中至多有100行,每行至多有100个字符. 2.电路走向在交叉点转90,其余部分沿直线传播.任意 两个交叉点都不相邻(竖直方向和水平方向). 3. 整个电路是连通的,不含残缺电路. 4. 两段电路之间不会交叉. 5. 门电路(与门,或门)的输入端与输出端都是水平的. 6. 取反运算的出现只会在紧挨门电路输入端之前,或紧 挨门电路输出端之后.(如上图所示)
1048
输入:
Follow My Logic
输入数据包含多个输入数据块.每个输入数据块包含以 下部分:
一个电路图,以上述形式表示,用只含'*'的单独一行结束. 多行01字符串,每行对应一组数据,包含26个0或1,分别对应AZ的值.用只含'*'的单独一行结束
输出:
对每组输入数据,输出对应的电路输出值. 每个结果占一行. 不同输入数据块的输出结果之间用空行隔开.
1048
思路
Follow My Logic
将逻辑电路表示成后缀表达式 根据输入求解后缀表达式
源程序
北京大学暑期课《ACMICPC竞赛训练》
北京大学暑期课《ACM/ICPC竞赛训练》
北京大学信息学院郭炜
guo_wei@
/guoweiofpku
课程网页:/summerschool/pku_acm_train.htm
动态规划北京大学信息学院郭炜
例题一、数字三角形(POJ1163)
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或右下走。只需要求出这个最大和即可,不必给出具体路径。
三角形的行数大于1小于等于100,数字为 0 - 99
输入格式:
5//三角形行数。下面是三角形7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
要求输出最大和
解题思路:
用二维数组存放数字三角形。
D( r, j) : 第r行第 j 个数字(r,j从1开始算)
MaxSum(r, j) : 从D(r,j)到底边的各条路径中,
最佳路径的数字之和。
问题:求 MaxSum(1,1)
典型的递归问题。
D(r, j)出发,下一步只能走D(r+1,j)或者D(r+1, j+1)。故对于N行的三角形:
if ( r == N)
MaxSum(r,j) = D(r,j)
else
MaxSum( r, j) = Max{ MaxSum(r+1,j), MaxSum(r+1,j+1) }
#include <iostream>
#include <algorithm>
#define MAX 101
using namespace std;
int D[MAX][MAX];
北京大学ACM暑期课讲义-SPFA算法
短路径估计值更新了,那么我们必须对所 有边的终点再做一次松弛操作;在SPFA算 法中,某个点的最短路径估计值更新,只 有以该点为起点的边指向的终点需要再做 一次松弛操作。在极端情况下,后者的效 率将是前者的n倍。
在平均情况下,SPFA算法的期望时间复杂
度为O(E)。
例题: POJ
2387 POJ 3256
SPFA算法
SPFA 全称 Shortest Path Faster Algorithm
基本应用为快速求解单源最短路
Spfa算法可以说是Bellman-ford算法的改 进版.spfa是利用队列来动态更新最小值.
SPFA算法实现
设Dist代表S到I点的当前最短距离,Fa代表
S到I的当前最短路径中I点之前的一个点的 编号。开始时Dist全部为+∞,只有 Dist[S]=0,Fa全部为0。 维护一个队列,里面存放所有需要进行迭 代的点。初始时队列中只有一个点S。用一 个布尔数组记录每个点是否处在队列中。
SPFA算法实现
每次迭代,取出队头的点v,依次枚举从v
出发的边v->u,设边的长度为len,判断 Dist[v]+len是否小于Dist[u],若小于则改进 Dist[u],将Fa[u]记为v,并且由于S到u的最 短距离变小了,有可能u可以改进其它的点, 所以若u不在队列中,就将它放入队尾。这 样一直迭代下去直到队列变空,也就是S到 所有节点的最短距离都确定下来,结束算 法。若一个点最短路被改进的次数达到n , 则有负权环。可以用spfa算法判断图有无负 权环
最短路算法(bellman-Ford算法)
最短路算法(bellman-Ford算法)
贝尔曼-福特算法与迪科斯彻算法类似,都以松弛操作为基础,即估计的最短路径值渐渐地被更加准确的值替代,直⾄得到最优解。在两个算法中,计算时每个边之间的估计距离值都⽐真实值⼤,并且被新找到路径的最⼩长度替代。然⽽,迪科斯彻算法以贪⼼法选取未被处理的具有最⼩权值的节点,然后对其的出边进⾏松弛操作;⽽贝尔曼-福特算法简单地对所有边进⾏松弛操作,共|V | − 1次,其中 |V |是图的点的数量。在重复地计算中,已计算得到正确的距离的边的数量不断增加,直到所有边都计算得到了正确的路径。这样的策略使得贝尔曼-福特算法⽐迪科斯彻算法适⽤于更多种类的输⼊。
贝尔曼-福特算法的最多运⾏O(|V|·|E|)次,|V|和|E|分别是节点和边的数量)。
贝尔曼-福特算法与迪科斯彻算法最⼤的不同:bellman-Ford算法可以存在负权边,⽽dijkstra算法不允许出现负权边;
bellman-Ford算法的步骤:
步骤1:初始化图
步骤2 :对每⼀条边进⾏松弛操作
步骤3:检查负权环
procedure BellmanFord(list vertices, list edges, vertex source)
// 该实现读⼊边和节点的列表,并向两个数组(distance和predecessor)中写⼊最短路径信息
// 步骤1:初始化图
for each vertex v in vertices:
if v is source then distance[v] := 0
else distance[v] := infinity
北大ACM题型
初级:一.基本算法:(1)枚举. (poj1753,poj2965)(2)贪心(poj1328,poj2109,poj2586)(3)递归和分治法.(4)递推.(5)构造法.(poj3295)(6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法:(1)图的深度优先遍历和广度优先遍历.(2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra) (poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)(3)最小生成树算法(prim,kruskal) (poj1789,poj2485,poj1258,poj3026)(4)拓扑排序 (poj1094)(5)二分图的最大匹配 (匈牙利算法) (poj3041,poj3020)(6)最大流的增广路算法(KM算法). (poj1459,poj3436)三.数据结构.(1)串 (poj1035,poj3080,poj1936)(2)排序(快排、归并排(与逆序数有关)、堆排) (poj2388,poj2299)(3)简单并查集的应用.(4)哈希表和二分查找等高效查找法(数的Hash,串的Hash) (poj3349,poj3274,POJ2151,poj1840,poj2002,poj2503)(5)哈夫曼树(poj3253)(6)堆(7)trie树(静态建树、动态建树) (poj2513)四.简单搜索(1)深度优先搜索 (poj2488,poj3083,poj3009,poj1321,poj2251)(2)广度优先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)五.动态规划(1)背包问题. (poj1837,poj1276)(2)型如下表的简单DP(可参考lrj的书 page149):1.E[j]=opt{D+w(i,j)} (poj3267,poj1836,poj1260,poj2533)2.E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1]+zij} (最长公共子序列) (poj3176,poj1080,poj1159)3.C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最优二分检索树问题)六.数学(1)组合数学:1.加法原理和乘法原理.2.排列组合.3.递推关系. (POJ3252,poj1850,poj1019,poj1942)(2)数论.1.素数与整除问题2.进制位.3.同余模运算. (poj2635, poj3292,poj1845,poj2115)(3)计算方法.1.二分法求解单调函数相关知识.(poj3273,poj3258,poj1905,poj3122)七.计算几何学.(1)几何公式.(2)叉积和点积的运用(如线段相交的判定,点到线段的距离等). (poj2031,poj1039)(3)多边型的简单算法(求面积)和相关判定(点在多边型内,多边型是否相交) (poj1408,poj1584)(4)凸包. (poj2187,poj1113)中级:一.基本算法:(1)C++的标准模版库的应用. (poj3096,poj3007)(2)较为复杂的模拟题的训练(poj3393,poj1472,poj3371,poj1027,poj2706)二.图算法:(1)差分约束系统的建立和求解. (poj1201,poj2983)(2)最小费用最大流(poj2516,poj2516,poj2195)(3)双连通分量(poj2942)(4)强连通分支及其缩点.(poj2186)(5)图的割边和割点(poj3352)(6)最小割模型、网络流规约(poj3308, )三.数据结构.(1)线段树. (poj2528,poj2828,poj2777,poj2886,poj2750)(2)静态二叉检索树. (poj2482,poj2352)(3)树状树组(poj1195,poj3321)(4)RMQ. (poj3264,poj3368)(5)并查集的高级应用. (poj1703,2492)(6)KMP算法. (poj1961,poj2406)四.搜索
北京大学ACM国际大学生程序设计竞赛课件3
李文新 2004.2 – 2004.6
内容提要
作业总结 - 1008 作业总结 - 1013 何林冬令营报告 – 称球问题 自学及讨论 – 征服者 作业
作业总结 - 1008
题意
Haab 19个月 前18个月每月20天 第19个月5天 0-19 月名 0-5 月名 Tzolkin 13个月 天数为20个轮转 1mix 2--- 3--- …
The problem
In each round, you will divide your soldiers into two groups in an arbitrary way. Then I will decide which one of them stays and which one goes home. Each soldier that stays will then move up one stair.
The problem
step – takes an array subset (with at least N1 elements), describing the group of soldiers you chose, and returns 1 or 2 as described above; the group of soldiers is specified by numbers of soldiers on each stair, as in the start function
北京大学ACM暑期课讲义-Bellman-ford算法共17页
•
29、在一切能够接受法律支配的人类 的状态 中,哪 里没有 法律, 那里就 没有自 由。— —洛克
•
30、风俗可以造就法律,也可以废除 法律。 ——塞·约翰逊
ford算法
46、我们若已接受最坏的,就再没有什么损失。——卡耐基 47、书到用时方恨少、事非经过不知难。——陆游 48、书籍把我们引入最美好的社会,使我们认识各个时代的伟大智者。——史美尔斯 49、熟读唐诗三百首,不会作诗也会吟。——孙洙 50、谁和我一样用功,谁就会和我一样成功。——莫扎特
北京大学ACM暑期课讲义-Bellman-
•
26、我们像鹰一样,生来就是自由的 ,但是 为了生 存,我 们不得 不为自 己编织 一个笼 子,然 后把自 己关在 里面。 ——博 莱索
ຫໍສະໝຸດ Baidu
•
27、法律如果不讲道理,即使延续时 间再长 ,也还 是没有 制约力 的。— —爱·科 克
•
28、好法律是由坏风俗创造出来的。 ——马 克罗维 乌斯
北京大学计算概论-课件:第七讲-算法
计算机科学家已经证明,只使用如下三种 结构,就可以描述任何算法,且算法结构 优良
顺序结构(Sequence) 分支结构(Decision) 循环结构(Repetition)
每一种基本结构分别只有一个入口和一个 出口
2 描述算法的三种基本结构
2019/11/11
北京大学
14
顺序结构:动作(语句)序列,
顺序执行,每个动作只执行一次, 各动作对执行结果产生的影响是 独立的
动作1 动作2 动作3 … 动作n
动作1 动作2 动作3
… 动作n
2.1 顺序结构
2019/11/11
北京大学
15
现实生活中的示例
按部就班 先来后到 循序渐进 接连不断
起床 刷牙 吃早饭 上课 吃中饭 午休 上课 吃晚饭 晚自习 洗漱 睡觉
2.2 分支结构
2019/11/11
北京大学
18
循环结构:重复执行
一系列动作
当 条件成立 做
动作1 动作2 … 动作n
循环结束处
条件成立? 否 是
动作1
… 动作n
2019/11/11
2.3 循环结构
北京大学
19
现实生活中的示例
周而复始 转圈 轮回
(第几周)如果小于20周
ACM暑期培训
{
cin>>szLine;
if(szLine[0]=='0') break;
len2=strlen(szLine);
for(i=len2-1,j=0;i>=0; i--)
an2[j++] = szLine[i] - '0';
addition(an1,an2,len1,len2);
学习改变命运,知 识创造未来
学习改变命运,知 识创造未来
ACM暑期培训
学习成就理想知识创造未来
参考程序
#include <iostream.h> #include <string.h> #define MAX_LEN 200 char szLine1[MAX_LEN + 10]; char szLine2[MAX_LEN + 10]; int an1[MAX_LEN + 10]; //被除数, an1[0]对应于个位 int an2[MAX_LEN + 10]; //除数, an2[0]对应于个位 int aResult[MAX_LEN + 10]; //存放商,aResult[0]对应于个位 //长度为 nLen1 的大整数p1 减去长度为nLen2 的大整数p2 //结果放在p1 里,返回值代表结果的长度 //如不够减返回-1,正好减完返回 0 int Substract( int * p1, int * p2, int nLen1, int nLen2) { int i; if( nLen1 < nLen2 ) return -1;
Bellman-ford算法
短路径长度; 算法的最终目的是计算出dist n-1 [u],为源点v到顶点u的最短路径长度。
2
dist k [u]的计算
采用递推方式计算 dist k [u]。
设已经求出 dist k-1 [u] , u = 0, 1, …, n-1,此即从源点v最多经过不构成负权 值回路的k-1条边到达终点u的最短路径的长度。
k
的值。
递推公式(求顶点u到源点v的最短路径): dist 1 [u] = Edge[v][u]
{ { } } dist k [u] = min dist k-1 [u], min dist k-1 [j] + Edge[j][u] , j=0,1,…,n-1,j≠u
3
例子
-1
1
6
-2
05
2
1
5 -2
if (Edge[i][j]<MAX && dist[j]>dist[i]+Edge[i][j]) return 0;//存在从源点可达的负权值回路
} } return 1;
8
算法复杂度分析
§ 假设图的顶点个数为n,边的个数为e。算法中有一个三重 嵌套的for循环,如果:
acm-icpc暑期课_最短路
acm-icpc暑期课_最短路
北京⼤学暑期课《ACM/ICPC 竞赛训练》
最短路算法
本讲义为四处抄袭后改编⽽成,来源已不可考。仅⽤于内部授课
北京⼤学信息学院郭炜 guo_wei@/doc/d83c4f84bb68a98270fefa4a.html
/doc/d83c4f84bb68a98270fefa4a.html /guoweiofpku
Dijkstra 算法
●
解决⽆负权边的带权有向图或⽆向图的单源最短路问题●贪⼼思想,若离源点s 前k-1近的点已经被确定,构成点集P ,那么从s 到离s 第k 近的点t 的最短路径,{s,p 1,p 2…p i ,t}满⾜s,p 1,p 2…p i ∈P 。
●否则假设pi ?P ,则因为边权⾮负,pi 到t 的路径≥0,则d[pi]≤d[t],pi 才是第k 近。将pi 看作t ,重复上⾯过程,最终⼀定会有找不到pi 的情况
●d[i]=min(d[p i ]+cost(p i ,i)),i ?P,p i ∈P d[t]=min(d[i]) ,i ?P
基本思想
●初始令d[s]=0,d[i]=+∞,P=?
●找到点i?P,且d[i]最⼩
●把i添⼊P,对于任意j?P,若d[i]+cost(i,j)
d[j]=d[i]+cost(i,j)。
●⽤邻接表,不优化,时间复杂度O(V2+E)
●Dijkstra+堆的时间复杂度 o(ElgV)
●⽤斐波那契堆可以做到O(VlogV+E)
●若要输出路径,则设置prev数组记录每个节点的前趋点,在d[i]
更新时更新prev[i]
北京大学ACM国际大学生程序设计竞赛(2)ppt课件
动态规划小结
▪ 递推公式 ▪ 存储构造及内容定义 ▪ 计算顺序 ▪ 从存储构造中复原问题的解
讨论
▪ Dividing 1014
作业
▪ Dividing 1014 ▪ A decorative fence 1037 提高
的高度取值〔不按陈列顺序〕分别为1,2,…,N。 把篱笆按其木条高度顺序记为:a1a2…aN,那么可
以对篱笆进展字典排序,例如:
问题描画
长度为 4 的美丽篱笆排序为:
1
2
3
4
5
6
7
8
9 10
问题描画
给定篱笆长度N和在该长度下的序号C,要求 给出第C中美丽篱笆的外形。
问题描画
样例输入: 2 21 33 样例输出: 12 231
问题解答
这样就可以根据给出的序号C,判别它落 在哪一个序号区间,从而得知它的第 一根木条的高度,去除第一根木条, 余下的问题就是一个N-1难度的问题, 可以运用同样的方法求解,直到最后 一根木条的高度被确定,整个问题就 处理了。
问题解答
这里需求留意的是,去掉第一根木条后, 余下的木条中比第一根木条高的木条 的高度要减一,才是完全的N-1难度问 题。
▪ 例:Fibonacci数 ▪ F(0)=0; F(1)=1; F(n)=F(n-1)+F(n-2); ▪ 递归: F(n-1)和F(n-2)分别求究竟一次 ▪ 动态规划:用数组将前n-1个数存起来,每次
ACM算法讲解
约5% 约10% 其它 约25%
5
纯数学题 数据结构
图作为一种非线性结构,被广泛应用于多个技术 领域。这一部分将是最难理解的,我们将先从基础知 识的讲解开始。
6
图论相关主题
• • • • • 第一阶段——图的遍历 第二阶段——最小生成树 第三阶段——最短路径 第四阶段——关键路径 第五阶段——拓扑排序
7
主题一、图的遍历
从图中的某个顶点出发,按某种方法对图中的 所有顶点访问且仅访问一次。
作用:是求解图的连通性问题、拓扑排序和求 关键路径等算法的基础。 为了保证图中的各顶点在遍历过程中访问且仅 访问一次,需要为每个顶点设一个访问标志,用以 标示图中每个顶点是否被访问过,访问标志用数组 visited[n]来表示。
8
深度优先搜索 图的遍历方法有两种: 广度优先搜索
9
深度优先搜索(DFS)——使用栈
深度优先搜索(Depth_First Search)是指按照深度 方向搜索 ,它类似于树的先根遍历。
深度优先算法的基本思想是:
(1)从图中某个顶点v0出发,首先访问v0。
(2)找出刚访问过的顶点vi的第一个未被访问的邻 接点,然后访问该顶点。重复此步骤,直到当前的 顶点没有未被访问的邻接点为止。 (3)返回前一个访问过的顶点,找出该顶点的下一 个未被访问的邻接点,访问该顶点。转2。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
✓ Bellman-Ford算法: ✓ 为了能够求解含负权边的带权有向图的单源最短路径问题, Bellman(贝尔曼)和Ford(福特)提出了从源点逐次绕过其他顶点, 以缩短到达终点的最短路径长度的方法。不能处理带负权边的无 向图。
✓ Bellman-Ford算法的限制条件: ✓ 要求图中不能包含权值总和为负值回路(负权值回路),如下图所 示。Why?
是否成立,如果成立,则说明存在从源点可达的负权值回路。代码如 下:
-2
1
0
7
1
2
(c)
1
Bellman-Ford算法思想
✓ Bellman-Ford算法构造一个最短路径长度数组序列dist 1 [u], dist 2 [u], …, dist n-1 [u]。其中: ❖ dist 1 [u]为从源点v到终点u的只经过一条边的最短路径长度,并 有dist 1 [u] =Edge[v][u]; ❖ dist 2 [u]为从源点v最多经过两条边到达终点u的最短路径长度; ❖ dist 3 [u]为从源点v出发最多经过不构成负权值回路的三条边到 达终点u的最短路径长度; …… ❖ dist n-1 [u]为从源点v出发最多经过不构成负权值回路的n-1条边 到达终点u的最短路径长度;
//对dist[ ]初始化
if( i!=v && dis[i]<MAX ) path[i] = v; //对path[ ]初始化
else path[i] = -1;
}
5
for(k=2; k<vexnum; k++) //从dist1[u]递推出dist2[u], …,distn-1[u]
{ for(u=0; u< vexnum; u++)//修改每个顶点的dist[u]和path[u]
7
如果存在从源点可达的负权值回路,则最短路径不存在,因 为可以重复走这个回路,使得路径无穷小。
在Bellman算法中判断是否存在从源点可达的负权值回路的 方法:
思路:在求出distn-1[ ]之后,再对每条边<u,v>判断一下:加入这条 边是否会使得顶点v的最短路径值再缩短,即判断:
dist[u]+w(u,v)<dist[v]
k dist k [0] dist k [1] dist k [2] dist k [3] dist k [4] dist k [5] dist k [6]
1
0
6
5
5
∞
∞
∞
2
0
3
3
5
5
4
∞
3
0
1
3
5
2
4
7
4
0
1
3
5
0
4
5
5
0
1
3
5
0
4
3
6
0
1
3 45
0
4源自文库
3
算法实现
注意: 1. 本算法使用同一个数组dist [u]来存放一系列的dist k [u] 。其中k = 0,
int vexnum; //顶点个数
int path[MAX_VER_NUM]; //path[i]是i在最短路径中的上一个节点
void BellmanFord(int v) //假定图的邻接矩阵和顶点个数已经读进来了
{
int i, k, u;
for(i=0; i<vexnum; i++)
{
dist[i]=Edge[v][i];
{
if( u != v )
{ for(i=0; i<vexnum; i++)//考虑其他每个顶点
{
if( Edge[i][u]<MAX &&
dist[u]>dist[i]+Edge[i][u] )
{
dist[u]=dist[i]+Edge[i][u];
path[u]=i;
}
}
} } }
如果dist[ ]各元素的初值为 MAX,则循环应该n-1次,
即k的初值应该改成1。
}
6
Dijkstra算法与Bellman算法的区别
§Dijkstra算法和Bellman算法思想有很大的区别: Dijkstra算法在求解过程中,源点到集合S内各顶点 的最短路径一旦求出,则之后不变了,修改的仅仅 是源点到T集合中各顶点的最短路径长度。 Bellman算法在求解过程中,每次循环都要修改所 有顶点的dist[ ],也就是说源点到各顶点最短路径长 度一直要到Bellman算法结束才确定下来。
递推公式(求顶点u到源点v的最短路径): dist 1 [u] = Edge[v][u] dist k [u] = min{ dist k-1 [u], min{ dist k-1 [j] + Edge[j][u] } }, j=0,1,…,n-
1,j≠u
3
例子
-1
1
6
-2
05
2
1
5 -2
-1
3 (c)
✓ 算法的最终目的是计算出dist n-1 [u],为源点v到顶点u的最短路径长 度。
2
dist k [u]的计算
✓ 采用递推方式计算 dist k [u]。 ❖ 设已经求出 dist k-1 [u] , u = 0, 1, …, n-1,此即从源点v最多经 过不构成负权值回路的k-1条边到达终点u的最短路径的长度。 ❖ 从图的邻接矩阵可以找到各个顶点j到达顶点u的距离 Edge[j][u],计算min{ dist k-1 [j] + Edge[j][u] } ,可得从源点 v绕过各个顶点,最多经过不构成负权值回路的k条边到达终点 u的最短路径的长度。 ❖ 比较dist k-1 [u]和min{ dist k-1 [j] + Edge[j][u] } ,取较小者作 为dist k [u]的值。
1, …, n-1。算法结束时中存放的是dist n-1 [u] 。 2. path数组含义同Dijkstra算法中的path数组。
#define MAX_VER_NUM 10 //顶点个数最大值
#define MAX 1000000
int Edge[MAX_VER_NUM][MAX_VER_NUM]; //图的邻接矩阵
01 23456
4
3
0 6
0
5 5 0
1
1
2 0 1 2
6
2 0
1
3
0 3 4
3
5
0 3 5 0 6
dist 2 [1] = min{ dist 1 [1], min{ dist 1 [j] + Edge[j][1] } } = min{6, min{dist1[0]+Edge[0][1], dist1[2]+Edge[2][1], … } }