差分约束
差分约束
给定包含 \(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;
}

浙公网安备 33010602011771号