题解 P5960 【【模板】差分约束算法】
Description
给定
Solution
差分约束模板,左边的这个
我们首先把这个不等式化简一下,成
假设
那我们再次假设如果
那么
因为要满足所有不等式,所以必须要取最小值来满足所有的不等式。
注意,我们上面提到的
那么我们可以再次简化模型。
假设有多个
那么我们看一下 SPFA 的递推式。
好了,破案了。
那么我们只需要找一个超级原点
最后我们求一个最短路即可,输出每个
最后无解的情况只需要判断一下负环即可。
Code
#include <bits/stdc++.h>
using namespace std;
struct node {
int val, next, len;
} e[100086];
int n, m;
int cnt;
int head[100086];
int dist[100086];
int sum[100086];
int vis[100086];
const int inf = 0x3f3f3f3f;
void AddEdge (int u, int v, int w) {
e[++cnt].val = v;
e[cnt].next = head[u];
e[cnt].len = w;
head[u] = cnt;
}
bool SPFA () {
queue <int> q;
int s = n + 1;
for (int i = 1; i <= n; i++)
dist[i] = inf;
dist[s] = 0;
sum[s] = 1;
vis[s]++;
q.push(s);
while (!q.empty()) {
int cur = q.front();
q.pop();
sum[cur] = 0;
for (int p = head[cur]; p > 0; p = e[p].next)
if (dist[e[p].val] > dist[cur] + e[p].len) {
dist[e[p].val] = dist[cur] + e[p].len;
vis[e[p].val]++;
if (vis[e[p].val] >= n + 1)
return true;
if (!sum[e[p].val]) {
q.push(e[p].val);
sum[e[p].val] = 1;
}
}
}
return false;
}
int main () {
scanf("%d%d", &n, &m);
for (int i = 1, u, v, w; i <= m; i++) {
scanf("%d%d%d", &u, &v, &w);
AddEdge(v, u, w);
}
for (int i = 1; i <= n; i++)
AddEdge(n + 1, i, 0);
if (SPFA()) {
printf("NO");
return 0;
}
int Min = 1e9;
for (int i = 1; i <= n; i++)
Min = min(dist[i], Min);
for (int i = 1; i <= n; i++)
printf("%d ", dist[i] - Min);
return 0;
}
2020.7.14
By Shuchong