POJ3259 Wormholes (Bellman-Ford最短路径算法)
2014-10-17 00:00
344 查看
本文出自:http://blog.csdn.net/svitter
原题:http://poj.org/problem?id=3259
题意:最基础的Bellman-Ford题目,寻找负环.告诉你有几个村庄,在村庄中有通路,通路走过去花费时间,通路是双向的,走虫洞可以使时间倒退,即负边.但是负边是单向的.
总结写在最前面:
Bellman-Ford算法最关键就在于判断有无负环;
Bellman-Ford算法刚刚自学,还不是很明白.一开始觉得使用邻接矩阵即可,想松弛n-1次以后看看还能不能再松弛,如果可以松弛说明有负环.一开始不过,心中甚是郁闷--(手懒不想写结构体..)实在无奈用了邻接表的形式(这才发现多写不了多少东西,输入的时候多加注意即可..)依然WA--这才好好看看了看..
问题在于:邻接表是对边处理,邻接矩阵则是对点处理.
在进行松弛操作的时候边的个数搞错了-=应该是m*2(双向边)+w(虫洞边)这才是最后的结果..也明白邻接表的速度要比邻接矩阵快的多..o(n^2)和O(n^3)明显不是一个级别--因此稀疏图还是要用邻接表.为了测试一下想法重写了邻接矩阵的算法,果然Time limit exception...不死心的我剪了剪枝还交了两次呵呵果然==再一次..
终于大彻大悟写了AC代码:
原题:http://poj.org/problem?id=3259
题意:最基础的Bellman-Ford题目,寻找负环.告诉你有几个村庄,在村庄中有通路,通路走过去花费时间,通路是双向的,走虫洞可以使时间倒退,即负边.但是负边是单向的.
总结写在最前面:
Bellman-Ford算法最关键就在于判断有无负环;
Bellman-Ford算法刚刚自学,还不是很明白.一开始觉得使用邻接矩阵即可,想松弛n-1次以后看看还能不能再松弛,如果可以松弛说明有负环.一开始不过,心中甚是郁闷--(手懒不想写结构体..)实在无奈用了邻接表的形式(这才发现多写不了多少东西,输入的时候多加注意即可..)依然WA--这才好好看看了看..
问题在于:邻接表是对边处理,邻接矩阵则是对点处理.
在进行松弛操作的时候边的个数搞错了-=应该是m*2(双向边)+w(虫洞边)这才是最后的结果..也明白邻接表的速度要比邻接矩阵快的多..o(n^2)和O(n^3)明显不是一个级别--因此稀疏图还是要用邻接表.为了测试一下想法重写了邻接矩阵的算法,果然Time limit exception...不死心的我剪了剪枝还交了两次呵呵果然==再一次..
终于大彻大悟写了AC代码:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define INF 0x1f1f1f1f int n, m ,w, e; int res[505]; struct Edge { int u; int v; int w; }; Edge edge[6000]; bool bellman(int n, int m, int src) { memset(res, 0x1f, sizeof(res)); res[src] = 0; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) { e = res[edge[j].u] + edge[j].w; res[edge[j].v] = res[edge[j].v] < e? res[edge[j].v] : e; } for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) { if(res[edge[j].v] > res[edge[j].u] + edge[j].w) return 1; } return 0; } void ace() { //work point; int i, j, k; //case int f; //num int s, e, c; scanf("%d", &f); while(f--) { scanf("%d%d%d", &n, &m, &w); // for(i = 0; i < m; i++) { scanf("%d%d%d", &s, &e, &c); //Two fields might be connected by more than one path. edge[i].u = s; edge[i].v = e; edge[i].w = c; edge[i + m].v = s; edge[i + m].u = e; edge[i + m].w = c; } //wormhole w += m * 2; for(i = m * 2; i < w; i++) { scanf("%d%d%d", &s, &e, &c); edge[i].u = s; edge[i].v = e; edge[i].w = -c; } m = w;//边数更改为w,包含虫洞,双向边. if(bellman(n, m, 1)) printf("YES\n"); else printf("NO\n"); } } int main() { ace(); return 0; }
相关文章推荐
- POJ3259 Wormholes (Bellman-Ford最短路径算法)
- POJ3259 Wormholes (Bellman-Ford最短路径算法)
- [图的最短路径算法]Dijkstra, Bellman-Ford, Floyd-Warshall
- 解析Bellman-Ford算法求最短路径
- 图论;单源最短路径;拓扑排序+松弛(有向无回路);Bellman-Ford(回路,负权回路);Dijkstra(无负权,可回路);可以用最小堆实现算法的优化;
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
- 算法导论-第24章- 单源最短路径 - 24.1 Bellman-Ford 算法
- (最短路径算法整理)dijkstra、floyd、bellman-ford、spfa算法模板的整理与介绍
- Bellman-Ford 算法实现单源最短路径
- 第七章 图(最短路径算法:dijkstra,bellman-ford,floyd)
- Bellman-Ford算法—求解带负权边的最短路径
- 单点最短路径算法 bellman-ford模板和队列优化后的spfa算法模板
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较
- Bellman-Ford 算法 单源最短路径问题
- 最短路径实现算法Bellman-Ford+Dijstra+Floyd
- 图算法:2、计算带有负权值的单源最短路径:Bellman-Ford算法
- java实现图的最短路径(SP)的贝尔曼福特(Bellman-Ford)算法
- 几大最短路径算法比较(Floyd & Dijkstra & Bellman-Ford & SPFA)
- 总结一下最短路径的贝尔曼-福特算法(Bellman-Ford)及用队列优化(spfa)