link
分析
一下是粗略的证明
先假设这样的解是存在的,对未知数Xi,假设一共有k组差分约束,则容易推出Xi <= min{ , , ,}
而通过建边用spfa得到的结果显然是满足这个条件的。为了维护图的连通性,需要加入超级源点
对于存在负环的情况,SPFA可以判断,此时负环的意义就是Xi <= Xi + 某负数,很显然不会存在符合差分约束的解。
code
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
int dis[N], inq[N], tot[N], head[N];
int n, m, cnt = 0;
struct edge{
int to, nxt, val;
}e[N];
inline void add(int u, int v, int w){
e[++cnt].to = v;
e[cnt].val = w;
e[cnt].nxt = head[u];
head[u] = cnt;
}
int spfa(){
queue<int> que;
que.push(0);
dis[0] = 0;
inq[0] = 1;
while (!que.empty()){
int u = que.front();
que.pop();
inq[u] = 0;
for (int i = head[u]; ~i; i = e[i].nxt) {
int v = e[i].to, w = e[i].val;
if (dis[v] > dis[u] + w){
dis[v] = dis[u] + w;
if (!inq[v]){
if (++tot[v] > n) return 0;
que.push(v);
inq[v] = 1;
}
}
}
}
return 1;
}
int main(){
#ifdef DEBUG
freopen("in.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
memset(head, -1, sizeof head);
memset(dis, 0x3f, sizeof dis);
cin >> n >> m;
for (int i = 0, u, v, w; i < m; ++i) {
cin >> u >> v >> w;
add(v, u, w);
}
for (int i = 1; i <= n; ++i) {
add(0, i, 0);
}
if (!spfa()) cout << "NO" << endl;
else
for (int i = 1; i <= n; ++i) {
cout << dis[i] << " ";
}
return 0;
}