poj3259 Wormholes BellmanFord或SPFA
来源:互联网 发布:佳为软件称软件 编辑:程序博客网 时间:2024/05/16 07:29
今天学了一下BellmanFord算法(它也是一个求单元最短路的算法),它和不使用优先队列的Dijkstra算法复杂度差不多,但是它可以处理带有负边权的图。
算法实现很简单:给定图G=(V, E), |V| = N。 (1)我们对所有边进行N-1次松弛操作可以得到源点到所有点的最短距离。(2)再对所有边进行一次松弛操作,判断是否存在负环,如果存在负环,则从S到所有点的最短距离不存在,否则求解完毕。
这道题题意:给定一些双向边(普通路径),边权为正,再给定一些单向边,边权为负,问是在这个图里否存在一个负环,存在负环就输出YES,否则输出NO。
直接用这个算法就A了。
#include<stdio.h>#include<string.h>const int N = 512;const int M = 6000; //邻接表存双向边要开边数的双倍const int INF = 0x3f3f3f3f;struct Edge { int v, w; int next;};int dis[N];int fir[N];Edge edge[M];int cnt, n;void init() { cnt = 1; memset(fir, -1, sizeof(fir));}void addEdge(int u, int v, int w) { edge[cnt].v = v; edge[cnt].w = w; edge[cnt].next = fir[u]; fir[u] = cnt++;}bool bellmanFord(int s) { memset(dis, INF, sizeof(dis)); dis[s] = 0; for(int i = 1; i < n; i++) { for(int j = 1; j <= n; j++) { for(int k = fir[j]; k != -1; k = edge[k].next) { int v = edge[k].v; if(dis[v] > dis[j] + edge[k].w) dis[v] = dis[j] + edge[k].w; } } } for(int j = 1; j <= n; j++) {// printf("[%d]\n", dis[j]); for(int k = fir[j]; k != -1; k = edge[k].next) { int v = edge[k].v; if(dis[v] > dis[j] + edge[k].w) return true; } } return false;}int main() { int f; scanf("%d", &f); while(f--) { init(); int m, w; scanf("%d%d%d", &n, &m, &w); for(int i = 0; i < m; i++) { int s, e, t; scanf("%d%d%d", &s, &e, &t); addEdge(s, e, t); addEdge(e, s, t); } for(int i = 0; i < w; i++) { int s, e, t; scanf("%d%d%d", &s, &e, &t); addEdge(s, e, -t); } if(bellmanFord(1)) printf("YES\n"); else printf("NO\n"); } return 0;}
Bellman-Ford能解决的通常SPFA都能解决(SPFA是Bellman-Ford的另一种实现方法,故SPFA也是求单元最短路),而且SPFA效率更高。
SPFA的主要步骤:
需要用的存储结构:
邻接表。
队列que<int>。
dis[ u ]:从源点S到u的最短距离。
vis[ u ]:u是否被访问过。
outque[ u ]: u出队的次数。
(1)源点S入队。
(2)访问队首元素,并让其出队,该点出队次数+1,判断该点出队次数是否大于N, 若果大于N则图中存在负环路,否则访问该点的所有连接边,进行松弛操作,如果可以松弛,则更新dis并且把当前顶点入队。
(3)重复(2)直到队列为空。
#include<stdio.h>#include<string.h>#include<queue>using namespace std;const int N = 512;const int M = 6000;const int INF = 0x3f3f3f3f;struct Edge { int v, w, next;};Edge edge[M];int fir[N];int outque[N];int vis[N], dis[N];int cnt, n;void init() { cnt = 1; memset(fir, -1, sizeof(fir));}void addEdge(int u, int v, int w) { edge[cnt].v = v; edge[cnt].w = w; edge[cnt].next = fir[u]; fir[u] = cnt++;}bool SPFA(int s) { memset(dis, INF, sizeof(dis)); memset(vis, 0, sizeof(vis)); memset(outque, 0, sizeof(outque)); queue<int> que; dis[s] = 0; que.push(s); while(!que.empty()) { int now = que.front(); outque[now] ++; if(outque[now] > n) return false; vis[now] = 0; que.pop(); for(int i = fir[now]; i != -1; i = edge[i].next) { int v = edge[i].v; if(dis[v] > dis[now] + edge[i].w) { dis[v] = dis[now] + edge[i].w; vis[v] = 1; que.push(v); } } } return true;}int main() { int f; scanf("%d", &f); while(f--) { int w, m; init(); scanf("%d%d%d", &n, &m, &w); for(int i = 0; i < m; i++) { int u, v, val; scanf("%d%d%d", &u, &v, &val); addEdge(u, v, val); addEdge(v, u, val); } for(int i = 0; i < w; i++) { int u, v, val; scanf("%d%d%d", &u, &v, &val); addEdge(u, v, -val); } if(!SPFA(1)) printf("YES\n"); else printf("NO\n"); } return 0;}
0 0
- poj3259 Wormholes BellmanFord或SPFA
- POJ3259 Wormholes【BellmanFord】
- poj3259 Wormholes(SPFA)
- [spfa+判负环]poj3259 Wormholes
- POJ3259-Wormholes(SPFA 判负环)
- SPFa-POJ3259-Wormholes
- POJ3259--Wormholes(SPFA)
- POJ3259 Wormholes(Bellmanford判断负环)
- poj3259 Wormholes --- bellman/spfa判负环
- POJ3259 Wormholes SPFA 或者 bellman_ford
- POJ3259 Wormholes 【Bellmanford判断是否存在负回路】
- POJ3259 Wormholes(虫洞)(SPFA解决)
- POJ3259 Wormholes 【SPFA判断负环】
- POJ3259----Wormholes(SPFA判断负环)
- poj3259 Wormholes(spfa判环)
- poj3259 Wormholes 最短路 spfa 负权环判断
- poj3259 - Wormholes
- Wormholes poj3259
- Linux下解决Android SDK更新“ Fetching https://dl-ssl.google.com/android/repository/addons_list-2.xml ”的问题
- 算法基础总结
- NOIp 2007 树网的核
- 最长回文子串
- Future-多线程设计模式
- poj3259 Wormholes BellmanFord或SPFA
- 软件测试6--软件测试与软件质量
- 019.数组的复制
- UFT(Unified Function Testing)自动化测试工具简介
- 1019. 数字黑洞 (20)
- 微信开发之带参二维码的使用
- SimpleJdbc: 用于简化数据库操作的Java库
- 操作系统哲学家就餐问题——定义一个互斥信号量mutex
- 华为之系统架构师作用的浅谈