本题其实也可以使用SPFA算法来求解的,不过就一个关键点,就是当某个顶点入列的次数超过所有顶点的总数的时候,就可以判断是有负环出现了。
SPFA原来也是可以处理负环的。
不过SPFA这种处理负环的方法自然比一般的Bellman Ford算法要慢点了。
#include <stdio.h> #include <string.h> #include <limits.h> const int MAX_N = 501; const int MAX_M = 2501; const int MAX_W = 201; struct Edge { int src, des, wei, next; //Edge(int s, int d, int w) : src(s), des(d), wei(w) {} }; Edge edge[(MAX_M<<1)+MAX_W]; int dist[MAX_N]; int head[MAX_N]; bool vis[MAX_N]; int qu[MAX_N]; int cnt[MAX_N]; int totalEdges; inline void insertEdge(int src, int des, int wei) { edge[totalEdges].src = src, edge[totalEdges].des = des; edge[totalEdges].wei = wei; edge[totalEdges].next = head[src]; head[src] = totalEdges++; } int N, M, W, F; bool cycleSPFA() { for (int i = 1; i <= N; i++) dist[i] = INT_MAX; dist[1] = 0; memset(vis, 0, sizeof(bool)*(N+1)); memset(cnt, 0, sizeof(int)*(N+1)); int top = 0, tail = 1; //循环队列的头和尾下标 qu[top] = 1; vis[1] = true; cnt[1] = 1; while (top < tail) { int u = qu[top%MAX_N]; //自定义循环队列 top++; vis[u] = false; for (int e = head[u]; e ; e = edge[e].next) { int v = edge[e].des; if (dist[u]+edge[e].wei < dist[v]) { dist[v] = dist[u]+edge[e].wei; if (!vis[v]) { vis[v] = true; qu[tail%MAX_N] = v; tail++; cnt[v]++; //记录入列次数 if (cnt[v] >= N) return true; } } } } return false; } int main() { int src, des, wei; scanf("%d", &F); while (F--) { scanf("%d %d %d", &N, &M, &W); memset(head, 0, sizeof(int) * (N+1)); totalEdges = 1; for (int i = 0; i < M; i++) { scanf("%d %d %d", &src, &des, &wei); insertEdge(src, des, wei); insertEdge(des, src, wei); } for (int i = 0; i < W; i++) { scanf("%d %d %d", &src, &des, &wei); insertEdge(src, des, -wei); } if (cycleSPFA()) puts("YES"); else puts("NO"); } return 0; }
POJ 3259 Wormholes SPFA算法题解,布布扣,bubuko.com
原文:http://blog.csdn.net/kenden23/article/details/37738183