洛谷5960:【模板】差分约束算法——题解
https://www.luogu.com.cn/problem/P5960
虽然说知道这玩意可是从来没写过……同时记录差分约束原理。
对于给定的式子$x-y\le c$,移动之得$x\le y+c$。
转换为图论模型,做起点,终点,权值为$y,x,c$的边,可发现如果我们对这个图跑最短路(先不要管怎么跑出来的233),那么一定有$dis[x]\le dis[y]+c$。
也就是说,此时每个点的$dis$值即为一组解,自然,有负环时无解。
现在就是怎么跑最短路的问题了,如果我们随便取一些点那么就会有一些点跑不到,就会出问题,于是我们设一个起点,对每条边连一条边权为0的单向边,这样我们只需要对这个起点跑一次spfa即可。
其本质是多构造了$u\le $起点的不等式。
#include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=5e3+5; const int M=1e4+5; const int INF=1e9; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct node{ int w,to,nxt; }e[M]; int n,m,k,p,cnt,head[N],dis[N],sum[N]; bool vis[N]; inline void add(int u,int v,int w){ e[++cnt].to=v;e[cnt].w=w;e[cnt].nxt=head[u];head[u]=cnt; } queue<int>q; bool spfa(int s){ for(int i=0;i<=n;i++)dis[i]=INF,sum[i]=0; q.push(s);vis[s]=1;dis[s]=0;sum[s]++; while(!q.empty()){ int u=q.front();q.pop();vis[u]=0; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to,w=e[i].w; if(dis[v]-w>dis[u]){ dis[v]=dis[u]+w; if(!vis[v]){ if(++sum[v]>=n+1)return 1; q.push(v);vis[v]=1; } } } } return 0; } int main(){ n=read(),m=read(); for(int i=1;i<=n;i++)add(0,i,0); for(int i=1;i<=m;i++){ int u=read(),v=read(),w=read(); add(v,u,w); } if(spfa(0))puts("NO"); else{ for(int i=1;i<=n;i++)printf("%d ",dis[i]); } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++