poj 3169 Layout 差分约束
设d[i] 为 第i只牛到第1只牛的距离
根据题意有:
d[1] = 0;
d[b] - d[a] <= D(ml)
d[b] – d[a] >= D(md)
d[i] – d[i-1] >= 0 题目说牛是从1~n排列下去,这是题目隐藏的条件,刚开始没有加这个条件也能ac
d[i] – d[1] >= 0 (1<= i <= n)
以1为源点开始搜索,d[n]就是答案,当d[n] = INF时,说明n是自由点,输出-2
#include <iostream> #include <queue> using namespace std; const int MAX = 50000; const int INF = 1000000000; const int N = 1005; struct Node { int v; int cost; int next; }; Node node[MAX]; int adj[N]; int d[N]; bool in_q[N]; queue<int> Q; int size; int n, ml, md; int cnt[N]; 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() { memset(in_q, false, sizeof(in_q)); memset(cnt, 0, sizeof(cnt)); for (int i = 0; i <= n; i++) d[i] = INF; d[1] = 0; in_q[1] = true; Q.push(1); int u, v, w; 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; } int main() { int a, b, c; scanf("%d%d%d", &n, &ml, &md); for (int i = 0; i <= n; i++) adj[i] = -1; size = 0; for (int i = 0; i < ml; i++) { scanf("%d%d%d", &a, &b, &c); add_edge(a, b, c); //d[b] - d[a] <= c } for (int i = 0; i < md; i++) { scanf("%d%d%d", &a, &b, &c); add_edge(b, a, -c); //d[a] - d[b] <= -c } for (int i = 2; i <= n; i++) { add_edge(i, 1, 0); //d[1] - d[i] <= 0 add_edge(i, i-1, 0); //d[i-1] - d[i] <= 0 } if (spfa()) { if (d[n] == INF) printf("-2\n"); else printf("%d\n", d[n]); } else printf("-1\n"); return 0; }