博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
求解单源最短路问题:Bellman-Ford算法(可判负权回路)详解 之 poj 3268 Silver Cow Party...
阅读量:5223 次
发布时间:2019-06-14

本文共 3478 字,大约阅读时间需要 11 分钟。

/*求解单源最短路问题:Bellman-Ford算法(可判负权回路)注:负权回路: 如果存在一个回路(首尾相同的路径),而且这个回路上所有权值之和是负数,那这就是一个负权回路。 f[i] := 从起点s出发到节点i的最短距离故:	f[i] = min(f[j] + dis[i][j]) 初始值:	f[] = INF	f[s] = 0; 自己当时遇到的疑惑,以及参考了相关资料获得的解答:(1)在实现时,最外侧循环的迭代次数为什么最大是|V|-1次?(|V|节点的个数)	答: 前提:在图中不存在负权回路		一共有n个节点,求1->n的最短距离,我们知道1->n的最短路径,最多有(n-1)条边。		(如果大于(n-1),说明有一个节点在最短路径上走了两次,即走了一个圈,			若圈的权为正:显然包含整个圈的路径必定不是最短路径;			若圈的权为负:最短路径不存在,因为到达节点的路径距离可以无限变小;			若圈的权为0: 去掉之后不影响最优解。		)		在每次循环中,我们利用f[i] = min(f[j] + dis[i][j])来更新(s->i)的边,每		次循环必定会更新成功一条边(更新成功指的是:这条边的权值也是最终最短路径的权值),		那么需要(n-1)次循环才可以更新掉所有的边。		在《数据结构与编程实验--大学生程序设计课程与竞赛训练教材》()上,                 有说到:			很多时候,需要的迭代次数远小于|V|-1,所以可以考虑在每次循环中设置的update的标记,			如果没有update,则说明已获得最优解,跳出循环即可。		时间复杂度:O(V*E) (2)为什么如果f[i]>f[j]+dis[j][i],可以判定有负权回路?	答: 根本原因:求解最短路时 f[i] = min(f[j] + dis[i][j])		在|V|-1此循环结束,即已获得最优解,如果在图中不存在负权回路,那么必然是f[i]<=f[j]+dis[j][i],		否则必然存在s->i的路径距离比f[i]更短,与已获得最优解矛盾。		代码:		for (int i = 0; i < eg.size(); ++i)		{			if (f[eg[i].egto] > f[eg[i].egfrom] + eg[i].egfrom)			{				return false; // 出现负权回路			}			return true; // 没有出现负权回路		}	eg: 初始: 边更新后: 3 > 0 + 2 => 出现负权回路 -------------------------------------------------------poj 3268 Silver Cow Party what is the longest amount of time a cow must spend walking to the party and back?故此题需要解决两个问题:	(1)所有节点到达节点X的最短距离;                  对于此问题,可以反过来想:从X节点到达所有节点的最短距离,答案不变。                  但是此时初始存储的有向边的方向需要调换                  (原因:路是单向的,a->b反过来想a<-b,边的方向发生了改变,                         边的权值不变,求解a->b的最短路也就是求a<-b的最短路                   )
(2)节点X到达所有节点的最短距离。		 按初始存储的有向边进行计算 答案:	max{ walkTo[i]+returnTo[i] } */
1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 using namespace std;18 const int INF = 0x3f3f3f3f;19 const int MaxN = 205;20 const int modPrime = 3046721;21 22 struct Edge23 {24 int egfrom, egto, egcost;25 };26 27 int N, M, X;28 Edge eg[100010];29 int walkTo[1010]; // cow walk to the party 30 int returnTo[1010]; // cow return to her farm31 32 void Solve()33 {34 bool update = true;35 fill(walkTo, walkTo + 1010, INF);36 walkTo[X] = 0;37 for (int i = 0; i < N && update; ++i)38 {39 update = false;40 for (int j = 0; j < M; ++j)41 {42 if ((walkTo[eg[j].egto] != INF) && (walkTo[eg[j].egfrom] > walkTo[eg[j].egto] + eg[j].egcost))43 {44 walkTo[eg[j].egfrom] = walkTo[eg[j].egto] + eg[j].egcost;45 update = true;46 }47 }48 }49 50 fill(returnTo, returnTo + 1010, INF);51 returnTo[X] = 0;52 update = true;53 for (int i = 0; i < N && update; ++i)54 {55 update = false;56 for (int j = 0; j < M; ++j)57 {58 if ((returnTo[eg[j].egfrom] != INF) && (returnTo[eg[j].egto] > returnTo[eg[j].egfrom] + eg[j].egcost))59 {60 returnTo[eg[j].egto] = returnTo[eg[j].egfrom] + eg[j].egcost;61 update = true;62 }63 }64 }65 66 int ans = 0;67 for (int i = 1; i <= N; ++i)68 {69 ans = max(ans, walkTo[i] + returnTo[i]);70 }71 cout << ans << endl;72 }73 74 int main()75 {76 #ifdef HOME77 freopen("in", "r", stdin);78 //freopen("out", "w", stdout);79 #endif80 81 cin >> N >> M >> X;82 for (int i = 0; i < M; ++i)83 {84 cin >> eg[i].egfrom >> eg[i].egto >> eg[i].egcost;85 }86 Solve();87 88 89 #ifdef HOME90 cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;91 _CrtDumpMemoryLeaks();92 #endif93 return 0;94 }
 

 

 

转载于:https://www.cnblogs.com/shijianming/p/5024831.html

你可能感兴趣的文章
c++ map
查看>>
exit和return的区别
查看>>
js += 含义(小知识)
查看>>
B2321 [BeiJing2011集训]星器 数学&&物理
查看>>
201571030319 四则运算
查看>>
RestTemplate 调用本地服务 connection refused
查看>>
.NET方向高级开发人员面试时应该事先考虑的问题
查看>>
台达PLC modbus 不支持04功能码
查看>>
发布一个JavaScript工具类库jutil,欢迎使用,欢迎补充,欢迎挑错!
查看>>
discuz 常用脚本格式化数据
查看>>
MS CRM 2011 创建基于Fetch的报表 -- 进阶版
查看>>
洛谷P2777
查看>>
PHPStorm2017设置字体与设置浏览器访问
查看>>
SQL查询总结 - wanglei
查看>>
安装cocoa pods时出现Operation not permitted - /usr/bin/xcodeproj的问题
查看>>
makefile中使用变量
查看>>
GIT笔记:将项目发布到码云
查看>>
JavaScript:学习笔记(7)——VAR、LET、CONST三种变量声明的区别
查看>>
JavaScript 鸭子模型
查看>>
SQL Server 如何查询表定义的列和索引信息
查看>>