SPFA
2016-07-13 04:41
239 查看
ACM模版
堆栈实现
参考题目链接
POJ 3159 Candies代码
const int INF = 0x3F3F3F3F; const int V = 30001; const int E = 150001; int pnt[E], cost[E], nxt[E]; int e, head[V]; int dist[V]; bool vis[V]; int relax(int u, int v, int c) { if (dist[v] > dist[u] + c) { dist[v] = dist[u] + c; return 1; } return 0; } inline void addedge(int u, int v, int c) { pnt[e] = v; cost[e] = c; nxt[e] = head[u]; head[u] = e++; } // 此处用堆栈实现,有些时候比队列要快 int SPFA(int src, int n) { int i; for (i = 1; i <= n; ++i) { // 顶点1...n vis[i] = 0; dist[i] = INF; } dist[src] = 0; int Q[E], top = 1; Q[0] = src; vis[src] = true; while(top) { int u, v; u = Q[--top]; vis[u] = false; for(i = head[u]; i != -1; i = nxt[i]) { v = pnt[i]; if(1 == relax(u, v, cost[i]) && !vis[v]) { Q[top++] = v; vis[v] = true; } } } return dist ; } int main() { int n, m; while (scanf("%d%d", &n, &m) != EOF) { int i, a, b, c; e = 0; memset(head, -1, sizeof(head)); for (i = 0; i < m; ++i) { // b-a <= c, 有向边(a, b):c ,边的方向!!! scanf("%d%d%d", &a, &b, &c); addedge(a, b, c); } printf("%d\n", SPFA(1, n)); } return 0; }
队列实现
参考题目链接
POJ 3169 Layout代码
/* * Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算。 * 它可以在O(kE)的时间复杂度内求出源点到其他所有点的最短路径,可以处理负边。 * 原理:只有那些在前一遍松弛中改变了距离估计值的点,才可能引起他们的邻接点的距离估计值的改变。 * 判断负权回路:记录每个结点进队次数,超过|V|次表示有负权。 */ #define swap(t, a, b) (t=a, a=b, b=t) const int INF = 0x3F3F3F3F; const int V = 1001; const int E = 20001; int pnt[E], cost[E], nxt[E]; int e, head[V], dist[V]; bool vis[V]; int cnt[V]; // 入队列次数 int relax(int u, int v, int c) { if (dist[v] > dist[u] + c) { dist[v] = dist[u] + c; return 1; } return 0; } inline void addedge(int u, int v, int c) { pnt[e] = v; cost[e] = c; nxt[e] = head[u]; head[u] = e++; } // 此处用队列实现 int SPFA(int src, int n) { int i; memset(cnt, 0, sizeof(cnt)); // 入队次数 memset(vis, false, sizeof(vis)); for (i = 1; i <= n; ++i) { dist[i] = INF; } dist[src] = 0; queue<int> Q; Q.push(src); vis[src] = true; ++cnt[src]; while(!Q.empty()) { int u, v; u = Q.front(); Q.pop(); vis[u] = false; for (i = head[u]; i != -1; i = nxt[i]) { v = pnt[i]; if (1 == relax(u, v, cost[i]) && !vis[v]) { Q.push(v); vis[v] = true; if ((++cnt[v]) > n ) { return -1; // cnt[i]为入队列次数,用来判断是否存在负权回路 } } } } if (dist == INF) { return -2; // src与n不可达,有些题目可省!!! } return dist ; // 返回src到n的最短距离,根据题意不同而改变 } int main() { int n, ml, md; while (scanf("%d%d%d", &n, &ml, &md) != EOF) { int i, a, b, c, t; e = 0; memset(head, -1, sizeof(head)); for (i = 0; i < ml; ++i) // 边方向!!! { // 大-小<=c,有向边(小, 大):c scanf("%d%d%d", &a, &b, &c); if (a > b) { swap(t, a, b); } addedge(a, b, c); } for (i = 0; i < md; ++i) { // 大-小>=c ==> 小-大<=-c,有向边(大, 小):-c scanf("%d%d%d", &a, &b, &c); if (a < b) { swap(t, a, b); } addedge(a, b, -c); } printf("%d\n", SPFA(1, n)); } return 0; }
相关文章推荐
- CSU1307 并查集+SPFA
- 最短路径 -- spfa
- 单源最短路深度分析
- hdoj 1874 畅通工程 vector邻接表测试
- USACO/butter 3.2.6
- 【POJ1860】Currency Exchange
- hdu 1596 find the safest road(spfa算法)
- MZ Training 2014 #8 F题
- MZ Training 2014 #4 B题
- [网络流24题 #18]分配问题
- [网络流24题 #18]分配问题
- 收益最大
- 对求最短路径常见算法的简单总结
- EOJ1848-你是ACM吗?
- acm-hdu2544解题报告
- hdu2112 spfa
- HDU 1317 POJ 1932 XYZZY
- POJ 3037 Skiing SPFA
- POJ 3255 Roadblocks 次短路 SPFA
- poj 1511 Invitation Cards