洛谷P5960 【模板】差分约束算法

作为一道模板题,没什么多说的。

正题:差分约束算法

1、x - y > z   =>   x > z + y   =>   add(x, y, -z)

2、虚拟源点0向各个点建边,权值为0   =>   add(0, i, 0)

2、用spfa算出最长路,直接输出就好了。

代码实现

#include 
#include 
using namespace std;
const int N = 1e6 + 10;
const int INF = 0x3f;
int st[N], n, m, w[N], ne[N], head[N], to[N], id, cnt[N], vis[N], dis[N], x, y, z, top;
void add(int x, int y, int z){
	to[++id] = y, ne[id] = head[x], w[id] = z, head[x] = id;
}
bool spfa(int u){
	memset (dis, -INF, sizeof dis);
	st[++top] = u, vis[u] = 1, dis[u] = 0, cnt[u]++;
	while(top){
		int t = st[top--];
		vis[t] = 0;
		for (int i = head[t]; i; i = ne[i]){
			int v = to[i];
			if (dis[v] < dis[t] + w[i]){
				dis[v] = dis[t] + w[i];
				if (!vis[v]){
					st[++top] = v, cnt[v]++, vis[v] = 1;
					if (cnt[v] > n)
						return 0;
				}
			}	
		}
	}
	return 1;
}
int main(){
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i++){
		scanf("%d%d%d", &x, &y, &z);
		add (x, y, -z);
	}
	for (int i = 1; i <= n; i++)
		add(0, i, 0);
	if (spfa(0))
		for (int i = 1; i <= n; i++)
			printf ("%d ", dis[i]);
	else
		printf ("NO");
}

你可能感兴趣的:(算法,图论)