POJ-2679(最短路+负环判断)
2014-06-18 11:06
169 查看
题目中节点数目很多(V<=1100),而边却较少(E <= 5000),因此SPFA的ElogE会明显优于Dijsktra的N^2
需要注意的是SPFA是处理入边邻接矩阵的,所以需要在SPFA处理之前根据输入的出边得到合法的入边
细节点:
(1)为处理单节点负环,队列节点出队后,应立即将对应节点的inq标志置为false
(2)题目要求输出时,先判断有无路径,再判断有无负环,所以在发现负环时,应先看dis[S][D]是否仍为无穷
![](http://img.blog.csdn.net/20140618110231343?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdXV1b3VvdWxjeg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
需要注意的是SPFA是处理入边邻接矩阵的,所以需要在SPFA处理之前根据输入的出边得到合法的入边
细节点:
(1)为处理单节点负环,队列节点出队后,应立即将对应节点的inq标志置为false
(2)题目要求输出时,先判断有无路径,再判断有无负环,所以在发现负环时,应先看dis[S][D]是否仍为无穷
#include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; #define MAX_VERTEX 1100 #define MAX_FEE 200 #define MAX_LENGTH 99999999 #define MAX_COST 99999999 /*********************** datas ***********************/ int N, M, S, D; struct Edge{ int to; int length; int cost; Edge(int t, int l, int c):to(t), length(l), cost(c){} }; vector<Edge> out[MAX_VERTEX], in[MAX_VERTEX]; int path[MAX_VERTEX][2]; int times[MAX_VERTEX]; bool inq[MAX_VERTEX]; /********************** procedures ********************/ bool input() { if(scanf("%d%d", &N, &M) != 2) return false; for(int i = 0; i < N; ++i){ out[i].clear(); in[i].clear(); } scanf("%d%d", &S, &D); int u, v, fuv, l, fvu; for(int i = 0; i < M; ++i){ while(getchar() != '(') ; scanf("%d,%d,%d[%d]%d)", &u, &v, &fuv, &l, &fvu); out[u].push_back(Edge(v, l, fuv)); out[v].push_back(Edge(u, l, fvu)); } return true; } void initInRoads() { for(int i = 0; i < N; ++i){ //find all rewarding roads leaving i vector<Edge>& v = out[i]; int k = v.size(); if(k > 1){ //find minimal fee int fee = MAX_FEE, j, n = k; for(j = 0; j < n; ++j){ if(v[j].cost < fee) fee = v[j].cost; } //erase all roads except those have minimal fee k = 0; for(j = 0; j < n; ++j){ if(v[j].cost == fee) v[k++] = v[j]; } } //set corresponding in roads for(int j = 0; j < k; ++j){ in[v[j].to].push_back(Edge(i, v[j].length, v[j].cost)); } } } void spfa() { //initialize memset(times, 0, N << 2); memset(inq, false, N); for(int i = 0; i < N; ++i){ path[i][0] = MAX_LENGTH; path[i][1] = MAX_COST; } path[D][0] = path[D][1] = 0; //main process queue<int> q; q.push(D); inq[D] = true; while(!q.empty()){ int u = q.front(); q.pop(); inq[u] = false; if(++times[u] > N){//negative cycle if(path[S][0] < MAX_LENGTH) puts("UNBOUND"); else puts("VOID"); return; } const vector<Edge>& vec = in[u]; for(int i = 0, n = vec.size(); i < n; ++i){ int v = vec[i].to; if(path[v][1] > path[u][1] + vec[i].cost || path[v][1] == path[u][1] + vec[i].cost && path[v][0] > path[u][0] + vec[i].length){ path[v][1] = path[u][1] + vec[i].cost; path[v][0] = path[u][0] + vec[i].length; if(!inq[v]){ q.push(v); inq[v] = true; } } } } if(path[S][0] < MAX_LENGTH) printf("%d %d\n", path[S][1], path[S][0]); else puts("VOID"); } int main() { while(input()){ initInRoads(); spfa(); } return 0; }
相关文章推荐
- 最短路 SPFA 判断负环 静态邻接表(链式前向星) HDU 2544 最短路 POJ 3259 Wormholes
- POJ-1860 Currency Exchange(贝尔曼最短路判断负环)
- POJ 3259 Wormholes (最短路 SPFA 判断负环)
- POJ - 3259 Wormholes(SPFA最短路判断负环)
- POJ:3259-Wormholes(最短路判断负环)
- POJ 1556 The Doors 判断线段相交+最短路
- POJ 3259 Wormholes 判断负环(spfa)
- POJ-1556 线段相交的判断与最短路(几何+图论)
- POJ 1556 The Doors 最短路floyd + 判断两线段相交
- POJ 3259 Wormholes(最短路,判断有没有负环回路)
- POJ-3259 Wormholes(判断负环、模板)
- 【POJ】1556 The Doors 最短路+判断线段相交
- poj&nbsp;3259spfa()判断是否存在负环
- poj 3259 bellman最短路判断有无负权回路
- Adventurous Driving - POJ 2679 最短路+负环
- poj 3259 Wormholes 【spfa判断是否存在负环】
- POJ 3259 Wormholes(最短路,判断有没有负环回路)
- POJ 3259 最短路 判负环
- POJ 1556 The Doors 最短路floyd + 判断两线段相交
- POJ:3259 Wormholes(SPFA判断负环)