poj 2983 Is the Information Reliable? 差分约束判断回路
这题加深我对差分约束的源点理解。
这题是判断图中是否存在环(用最短路或最长路), 开始用spfa, 狂WA,想不通,看了讨论说要添加一个超源点,添加了就AC了。
总结:用spfa算法判断图中是否存在环,要保证从源点开始,能到达各个顶点,这样才能保证差分约束里的各个不等式成立。因为要是源点到达不了某个顶点的话(即图是不连通的),那么从该顶点就无法入队,导致从该顶点出发的所有不等式,都没有得到检查。
而是使用bellman_ford算法,则不用添加超源点,因为它对图中每一条边都为做n-1次松弛,就保证每个顶点都得到更新。
#include <iostream> #include <queue> using namespace std; const int MAX = 500000; const int INF = 1000000000; const int N = 2000; struct Node { int v; int cost; int next; }; Node node[MAX]; int cnt[N]; int adj[N]; bool in_q[N]; int d[N]; int size; int n, m; void add_edge(int u, int v, int cost) { node[size].v = v; node[size].cost = cost; node[size].next = adj[u]; adj[u] = size++; } bool spfa() { queue<int> Q; memset(cnt, 0, sizeof(cnt)); memset(in_q, false, sizeof(in_q)); for (int i = 0; i <= n; i++) d[i] = -INF; int u,v,w; //从超源点开始搜索 d[0] = 0; in_q[0] = true; Q.push(0); while (!Q.empty()) { u = Q.front(); Q.pop(); in_q[u] = false; for (int i = adj[u]; i != -1; i = node[i].next) { v = node[i].v; w = node[i].cost; if (d[v] < d[u]+w) { d[v] = d[u] + w; if (!in_q[v]) { in_q[v] = true; Q.push(v); if (++cnt[v] >= n) return false; } } } } return true; } bool bellman_ford() { for (int i = 0; i <= n; i++) d[i] = -INF; bool isfinish; for (int i = 1; i <= n; i++) { isfinish = true; for (int u = 0; u <= n; u++) for (int k = adj[u]; k != -1; k = node[k].next) if (d[node[k].v] < d[u] + node[k].cost) { d[node[k].v] = d[u] + node[k].cost; isfinish = false; } if (isfinish) break; } for (int u = 0; u <= n; u++) for (int k = adj[u]; k != -1; k = node[k].next) if (d[node[k].v] < d[u] + node[k].cost) return false; return true; } int main() { char c; int a, b ,w; while (scanf("%d%d", &n, &m) != EOF) { size = 0; for (int i = 0; i <= n; i++) adj[i] = -1; for (int i = 0; i < m; i++) { getchar(); scanf("%c", &c); if (c == 'P') { scanf("%d%d%d", &a, &b, &w); add_edge(b, a, w); add_edge(a, b, -w); } else if (c == 'V') { scanf("%d%d", &a, &b); add_edge(b, a, 1); } } //使用bellman就不需要添加超源点 //添加超源点到所有点的边 //for (int i = 1; i <= n; i++) // add_edge(0, i, 0); if (bellman_ford()) printf("Reliable\n"); else printf("Unreliable\n"); } return 0; }