一, 描述
差分约束算法即对一组不等式求解,如上题.有ai-aj<k可以转化为ai<k+aj.
我们突然发现这是一个最短路的形式 -- 具体来说, ai≤aj+k,根据上述分析,我们可以将其转化为从 j 到 i 的一条长度为 k的边,那么 ai 就转化成了源点到 i 的最短路径距离。如果题目无解就相当于有负环存在.
但需要注意的是这个图可能是不连通的,即从一个点出发有些点一定无法到达.此时对于SPFA算法来说直接使用是不可以的,需要构建一个超级源点0,该点将连接所有点,并且距离为0.以该点为源点放入队列中.
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 5e3 + 10, inf = 1e9;
int dis[maxn];
int n, m;struct edge {//直接存边法
int u, v, w;
}edge[maxn];bool BFord()
{
for (int i = 1; i <= n; i++) {
dis[i] = inf;//初始化所有点到源点的距离
}
dis[1] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
dis[edge[j].v] = min(dis[edge[j].u] + edge[j].w, dis[edge[j].v]);//将所有点都松弛一遍,重复点的个数次
}
}
for (int j = 1; j <= m; j++) {//将所有边遍历一次,如果有边还可以松弛则表示有负环,无解
if (dis[edge[j].u] + edge[j].w < dis[edge[j].v])return false;//
}
return true;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) cin >> edge[i].v >> edge[i].u >> edge[i].w;
if (BFord())
{
for (int i = 1; i <= n; i++) printf("%d ", dis[i]);
}
else printf("NO\n");
return 0;}