poj 3259
SPFA加邻接矩阵勉强过了
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <cstdlib> 5 #include <cmath> 6 #include <map> 7 #include <algorithm> 8 #include <list> 9 #include <ctime> 10 #include <set> 11 #include <string.h> 12 #include <queue> 13 #include <cstdio> 14 using namespace std; 15 typedef int typep; 16 int maxData = 500000; 17 #define N 505 18 #define CLR(arr, what) memset(arr, what, sizeof(arr)) 19 int path[N][N]; 20 int d[N]; 21 int n; 22 //double maxData = 0; 23 24 bool relax(typep u, typep& v, typep w) { 25 if (v > (u + w)) { 26 v = u + w; 27 return true; 28 } else 29 return false; 30 } 31 32 bool bellman_ford(int s) { 33 //int n = d.size(); 34 int i, j, k; 35 bool judge; 36 37 for (i = 0; i < n - 1; i++) { 38 for (j = 0; j < n; j++) { 39 for (k = 0; k < n; k++) { 40 if (path[j][k] != maxData && d[j] != maxData) 41 judge = relax(d[j], d[k], path[j][k]); 42 } 43 } 44 } 45 46 for (j = 0; j < n; j++) { 47 for (k = 0; k < n; k++) { 48 if (path[j][k] != maxData && d[j] != maxData) { 49 judge = relax(d[j], d[k], path[j][k]); 50 if (judge) { 51 return true; 52 } 53 } 54 55 } 56 } 57 58 return false; 59 } 60 61 62 int cnt[N];//记录顶点入队列次数 63 bool final[N];//记录顶点是否在队列中,SPFA算法可以入队列多次 64 bool SPFA(int s) { 65 queue<int> myqueue; 66 int i; 67 CLR(final,0); 68 CLR(cnt,0); 69 final[s] = true; 70 cnt[s]++; //源点的入队列次数增加 71 myqueue.push(s); 72 int topint; 73 bool judge; 74 while (!myqueue.empty()) { 75 topint = myqueue.front(); 76 myqueue.pop(); 77 final[topint] = false; 78 for (i = 0; i < n; ++i) { 79 if (d[topint] < maxData) { 80 judge = relax(d[topint], d[i], path[topint][i]); 81 if (judge) { 82 if (!final[i]) { //判断是否在当前的队列中 83 final[i] = true; 84 cnt[i]++; 85 if (cnt[i] >= n) //当一个点入队的次数>=n时就证明出现了负环。 86 return true; 87 myqueue.push(i); 88 } 89 } 90 } 91 } 92 } 93 return false; 94 } 95 96 int main() { 97 int f, m, w, u, v, c, t; 98 cin >> f; 99 for (int abc = 0; abc < f; abc++) { 100 scanf("%d%d%d", &t, &m, &w); 101 n = t + 1; 102 CLR(path, maxData); 103 for (int i = 0; i < t; i++) { 104 path[0][i + 1] = 0; 105 } 106 for (int i = 0; i < m; i++) { 107 scanf("%d %d %d", &u, &v, &c); 108 path[u][v] = min(path[u][v], c); 109 path[v][u] = min(path[v][u], c); 110 } 111 for (int i = 0; i < w; i++) { 112 scanf("%d %d %d", &u, &v, &c); 113 path[u][v] = min(path[u][v], 0 - c); 114 } 115 int judge = false; 116 CLR(d, maxData); 117 d[0] = 0; 118 //judge = bellman_ford(0); 119 judge = SPFA(0); 120 if (judge) { 121 cout << "YES" << endl; 122 } else { 123 cout << "NO" << endl; 124 } 125 } 126 return 0; 127 }
对于这种稀疏矩阵,邻接表的方法更快,附代码
#include <iostream> #include <string> #include <vector> #include <cstdlib> #include <cmath> #include <map> #include <algorithm> #include <list> #include <ctime> #include <set> #include <string.h> #include <queue> #include <cstdio> using namespace std; typedef int typep; const int E = 10000; const int V = 600; #define typec int // type of cost const typec inf = 1000000; // max of cost int n, m, pre[V], edge[E][3]; typec dist[V]; int relax(typec u, typec v, typec c) { if (dist[v] > dist[u] + c) { pre[v] = u; dist[v] = dist[u] + c; return 1; } return 0; } int bellman(int src) { int i, j; for (i = 0; i < n; ++i) { dist[i] = inf; pre[i] = -1; } dist[src] = 0; bool flag; for (i = 1; i < n; ++i) { flag = false; // 优化 for (j = 0; j < m; ++j) { if (1 == relax(edge[j][0], edge[j][1], edge[j][2])) flag = true; } if (!flag) break; } for (j = 0; j < m; ++j) { if (1 == relax(edge[j][0], edge[j][1], edge[j][2])) return 0; // 有负圈 } return 1; } inline void addedge(int u, int v, typec c) { edge[m][0] = u; edge[m][1] = v; edge[m][2] = c; m++; } int main() { int f, mt, w, u, v, c, t; cin >> f; for (int abc = 0; abc < f; abc++) { scanf("%d%d%d", &t, &mt, &w); n = t + 1; m = 0; for (int i = 0; i < t; i++) { addedge(0, i + 1, 0); } for (int i = 0; i < mt; i++) { scanf("%d %d %d", &u, &v, &c); addedge(u, v, c); addedge(v, u, c); } for (int i = 0; i < w; i++) { scanf("%d %d %d", &u, &v, &c); addedge(u, v, -c); } int judge = false; judge = bellman(0); if (!judge) { cout << "YES" << endl; } else { cout << "NO" << endl; } } return 0; }