D118 最短路→差分约束 SPFA 算法 P4878 [USACO05DEC] Layout G 排队布局
D118 最短路→差分约束 SPFA 算法 P4878 [USACO05DEC] Layout G 排队布局_哔哩哔哩_bilibili
P4878 [USACO05DEC] Layout G - 洛谷
给 n 个点,m1+m2 个约束条件,求最大解。
思路
不等式的约束条件:
1. 相邻编号的牛之间的距离大于等于 0,即 $i-(i-1)\ge 0$
2. 基友 $a,b$ 之间的距离小于等于 $c$,即 $b-a\le c$
3. 情敌 $a,b$ 之间的距离大于等于 $c$,即 $b-a\ge c$
因为求最大解,把约束条件均转化为 $\le$,建图,跑最短路,判负环
判负环时,把所有点入队,以免走不到负环。不存在负环时,从 1 号点开始搜索,答案在 d[n]

相关板子:
D116【模板】最短路→差分约束 SPFA 算法 P5960 差分约束 - 董晓 - 博客园
// 差分约束 SPFA 算法 O(NM) #include<bits/stdc++.h> using namespace std; const int N=1005,M=21005; int h[N],to[M],ww[M],ne[M],idx; void add(int a,int b,int c){ to[++idx]=b,ww[idx]=c,ne[idx]=h[a],h[a]=idx; } int n,m1,m2; int d[N],cnt[N]; bool vis[N]; bool spfa(int siz){ memset(d,0x3f,sizeof d); memset(vis,0,sizeof vis); memset(cnt,0,sizeof cnt); queue<int> q; for(int i=1;i<=siz;i++)d[i]=0,q.push(i),vis[i]=true; while(!q.empty()){ int u=q.front();q.pop();vis[u]=false; for(int i=h[u]; i; i=ne[i]){ int v=to[i]; if(d[v]>d[u]+ww[i]){ d[v]=d[u]+ww[i]; //最短路 cnt[v]=cnt[u]+1; //走过的边数 if(cnt[v]>=n) return true; //有负环 if(!vis[v]) q.push(v),vis[v]=true; } } } return false; } int main(){ scanf("%d%d%d",&n,&m1,&m2); for(int i=1; i<=n; i++){ add(i,i-1,0); //(i-1)-i<=0 } for(int a,b,c;m1--;){ scanf("%d%d%d",&a,&b,&c); add(a,b,c); //b-a<=c } for(int a,b,c;m2--;){ scanf("%d%d%d",&a,&b,&c); add(b,a,-c); //a-b<=-c } if(spfa(n)) puts("-1"); //有负环则无解 else{ spfa(1); if(d[n]==0x3f3f3f3f) puts("-2"); //无穷大 else printf("%d\n",d[n]); } }
浙公网安备 33010602011771号