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;
}

from kakamilan

原文地址:https://www.cnblogs.com/kakamilan/p/3075889.html