POJ 3259 Wormholes(判断负环&(Bellman-Ford|SPFA))
2016-01-15 20:29
603 查看
题目链接:kuangbin带你飞 专题四 最短路练习 F - Wormholes
Bellman-Ford和SPFA都可以进行负环的判断,因为这两个算法以前都没用过,索性就都写了一下,慢慢熟练。
SPFA是对Bellman-Ford进行队列优化的改进版,但提交后反而比Bellman-Ford慢,这点挺奇怪的。
不知道是数据的原因,还是什么?
题意
农场主拥有很多农场,在这些农场之间有很多条路,以及单向的虫洞,每条路走完会花费一定的时间,而冲动可以回到之前的时间,问农场主是否可以通过特定的路径看到出发前的自己?(也就是回到自己出发时间前的出发点)思路
将农场看做点,路和虫洞看做边,那么显然虫洞是负权边,这样题目就转化为求给定图中是否有负环的问题了。Bellman-Ford和SPFA都可以进行负环的判断,因为这两个算法以前都没用过,索性就都写了一下,慢慢熟练。
SPFA是对Bellman-Ford进行队列优化的改进版,但提交后反而比Bellman-Ford慢,这点挺奇怪的。
不知道是数据的原因,还是什么?
代码
Bellman-Ford
#include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<algorithm> using namespace std; const int N = 509; const int MAX = 0x3f3f3f3f; struct Edge { int u, v, r; }edge[N*N+200]; int d ; bool Bellman_Ford(int n, int e, int src) { for(int i=1; i<=n; i++) d[i] = MAX; d[src] = 0; while(d[src] >= 0) { bool flag = true; for(int i=0; i<e; i++) { int u = edge[i].u; int v = edge[i].v; int to = d[u] + edge[i].r; if(d[v] > to) { d[v] = to; flag = false; } } if(flag) return d[src] < 0; } return 1; } int main() { int T; scanf("%d", &T); while(T--) { int n, m, w; scanf("%d%d%d", &n, &m, &w); for(int i=0; i<m; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); edge[i].u = a; edge[i].v = b; edge[i].r = c; edge[i+m].u = b; edge[i+m].v = a; edge[i+m].r = c; } for(int i=0; i<w; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); edge[2*m+i].u = a; edge[2*m+i].v = b; edge[2*m+i].r = -c; } if(Bellman_Ford(n, m*2+w, 1)) printf("YES\n"); else printf("NO\n"); } return 0; }
SPFA
#include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<algorithm> #include<queue> using namespace std; const int N = 509; const int MAX = 0x3f3f3f3f; struct Edge { int u, v, r, next; }edge[N*N+200]; int d ; int h ; bool vis ; int cnt ; bool spfa(int n) { memset(vis, 0, sizeof(vis)); memset(cnt, 0, sizeof(cnt)); for(int i=1; i<=n; i++) d[i] = MAX; d[1] = 0; vis[1] = 1; cnt[1]++; queue<int> q; q.push(1); while(!q.empty()) { int x = q.front(); vis[x] = 0; q.pop(); for(int i = h[x]; i!=-1; i = edge[i].next) { int v = edge[i].v; int to = edge[i].r + d[edge[i].u]; if(d[v] > to) { d[v] = to; if(!vis[v]) { vis[v] = 1; q.push(v); if(++cnt[v] > n) return 1; } } } } return 0; } int main() { int T; scanf("%d", &T); while(T--) { int n, m, w; memset(h, -1, sizeof(h)); scanf("%d%d%d", &n, &m, &w); for(int i=0; i<m; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); edge[i].next = h[a]; edge[i].u = a; edge[i].v = b; edge[i].r = c; h[a] = i; edge[i+m].next = h[b]; edge[i+m].u = b; edge[i+m].v = a; edge[i+m].r = c; h[b] = i+m; } for(int i=0; i<w; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); edge[2*m+i].next = h[a]; edge[2*m+i].u = a; edge[2*m+i].v = b; edge[2*m+i].r = -c; h[a] = 2*m+i; } if(spfa(n)) printf("YES\n"); else printf("NO\n"); } return 0; }
相关文章推荐
- 2016 系统设计第一期 (档案一)MVC 引用 js css
- block
- 老人真是饿了(贪心)
- linux删除普通用户报错 userdel: user fancy is currently used by process 1973
- 内存管理
- 寻找和为定值的任意个数(01背包)
- JS this指向
- 重拾编程之路-- Reverse Bits
- 2.7 过程表示
- 【应用】线性表的删除
- Markdown速成班
- Flume1.5.0入门:安装、部署、及flume的案例
- AlertDialog的onCreateDialog与onPrepareDialog用法
- iOS 【Multithreading-线程间的交互通信(图片下载示例)(掌握)】
- Hdoj 3047 Zjnu Stadium
- 手把手教你配置Hbase完全分布式环境
- ZOJ1516 Uncle Tom's Inherited Land(二分图最大匹配)
- 使用libsvm实现文本分类
- for循环
- zzulioj--1858--单词翻转(模拟)