差分约束

例题链接

差分约束

给定包含 \(n\) 个未知数 \(x_1,x_2,\cdots,x_n\) 的不等式组:

\[\begin{cases} x_{a_1}-x_{b_1}\leq y_1\\ x_{a_2}-x_{b_2}\leq y_2\\ \cdots\\ x_{a_m}-x_{b_m}\leq y_m \end{cases} \]

求其任意整数解,或报告无解。

最短路

考虑将 \(x_{a_i}-x_{b_i}\leq y_i\) 转化,得到 \(x_{a_i}\leq x_{b_i}+y_i\)。考虑最短路问题,设 \(\textit{dis}_x\)\(x\) 的最短路,发现对于边 \((x,v)\),在最短路确定之后,有 \(\textit{dis}_v\leq\textit{dis}_{x}+w_{x,v}\)

因此考虑在一张有向图上从 \(b_i\)\(a_i\) 连权值为 \(y_i\) 的边,跑最短路即可。

最短路的起点一般设置一个不存在的 \(0\) 号点,\(0\) 向所有点连权值为 \(0\) 的有向边。相当于 \(x_0\leq x_i\)


无解即存在负环,Bellman-Ford 判断即可。

AC 代码

//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
constexpr const int N=5e3,inf=0x3f3f3f3f;
int n,dis[N+1];
vector<pair<int,int>>g[N+1];
bool BellmanFord(){
	memset(dis,0x3f,sizeof(dis));
	dis[0]=0;
	for(int i=0;i<=n;i++){
		bool flag=true;
		for(int x=0;x<=n;x++){
			if(dis[x]==inf){
				continue;
			}
			for(auto [v,w]:g[x]){
				if(dis[x]+w<dis[v]){
					dis[v]=dis[x]+w;
					flag=false;
				}
			}
		}
		if(flag){
			return false;
		}
	}
	return true;
}
int main(){
	/*freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);*/
	
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	int m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		g[0].push_back({i,0});
	}
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		g[v].push_back({u,w});
	}
	if(BellmanFord()){
		cout<<"NO\n";
	}else{
		for(int i=1;i<=n;i++){
			cout<<dis[i]<<' ';
		}
	}
	
	cout.flush();
	
	/*fclose(stdin);
	fclose(stdout);*/
	return 0;
}
posted @ 2025-11-25 15:13  TH911  阅读(3)  评论(0)    收藏  举报