差分约束是为了解决这样一组不等式问题:
 
 这个咋解决》我们来看
 对于某个下标k而言,提取出关于其的所有不等式,(其中xk在第一个),也就是
xk-x1<=m1
xk-x2<=m2
xk-x3<=m3....
对于这些不等式相当于是
 xk取min(x1+m1,x2+m2,x3+m3,…)
 那么这个时候如果可以想到图论算法的话就是,从x1,x2,x3…这些点连出一条指向xk的边,权值为m1,m2,m3,…(我之前写错是因为边连反了,权值也是反的,)用最短路算法来解决这个问题,那么就变成:求一个源点到各个点的最短路问题,这个时候,注意无解的情况,如果存在一个负权环负权环的定义应为环上的权值之和为负值,那么就说明出现了循环关系,也就是,我们来看:
x1-x2<=-1
x2-x3<=-2
x3-x1<=-2
这个是个怪圈也就是无解的情况。
 那如果有正权环呢?
 我们来看
x1-x2<=1
x2-x3<=2
x3-x1<=2
如果x1取1,那么x2可以取0,x3可以取-2
 他们的大小关系是不一定的
 但是上面那个怪圈是出现了循环小于的情况,所以无解
 正权环可以理解成x1可能比x2大一点,但也有可能小于x2,负权的时候是一定小于
 如果你觉得本蒟蒻写的不咋地,请移步:
 神犇的讲解
 题:
 差分约束算法
 注意由于有负权环,又需要检查负权环,所以使用Bellman-Ford算法即可
 代码:
#include<bits/stdc++.h>
using namespace std;
#define INT_MAX 0x3f3f3f3f
const int length = 5e3 + 5;
vector<pair<pair<int, int>, int>> edge;
int dp[length];
int main(void)
{
	int n, m;
	scanf_s("%d%d", &n, &m);
	for (int i = 0; i < m; i++)
	{
		int a, b, c;
		scanf_s("%d%d%d", &a, &b, &c);
		edge.push_back({ {b,a},c });
	}
	//使用b_f算法
	for (int i = 1; i <= n; i++)
	{
		dp[i] = INT_MAX;
	}
	for (int i = 0; i < n - 1; i++)
	{
		for (int i = 0; i < m; i++)
		{
			int a = edge[i].first.first;
			int b = edge[i].first.second;
			int c = edge[i].second;
			dp[b] = min(dp[a] + c, dp[b]);
		}
	}
	int flag = 1;
	for (int i = 0; i < m; i++)
	{
		int a = edge[i].first.first;
		int b = edge[i].first.second;
		int c = edge[i].second;
		if (dp[b] > dp[a] + c)
		{
			flag = 0;
			break;
		}
	}
	if (flag == 0)
	{
		printf("NO");
	}
	else
	{
		for (int i = 1; i <= n; i++)
		{
			printf("%d ", dp[i]);
		}
	}
}









![[附源码]java毕业设计网上书店系统](https://img-blog.csdnimg.cn/683583f907194d3e8953113b5338fa74.png)









