AcWing1170 排队布局(差分约束)
对于第二问和第三问,只需要把1作为绝对值0点,即可在物理意义上解决,差分约束的关键是找到所有关系,一般而言,如果题目没给,可以考虑超级原点。
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; const int inf=0x3f3f3f3f; int h[N],e[N],ne[N],w[N],idx; int dis[N]; int st[N]; int cnt[N]; void add(int a,int b,int c){ e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++; } int n,m,k; bool spfa(int x){ memset(dis,0x3f,sizeof dis); memset(cnt,0,sizeof cnt); memset(st,0,sizeof st); queue<int> q; for(int i=1;i<=x;i++){ q.push(i); dis[i]=0; st[i]=1; } while(q.size()){ int t=q.front(); q.pop(); st[t]=0; int i; for(i=h[t];i!=-1;i=ne[i]){ int j=e[i]; if(dis[j]>dis[t]+w[i]){ dis[j]=dis[t]+w[i]; cnt[j]=cnt[t]+1; if(cnt[j]>=n) return false; if(!st[j]){ q.push(j); st[j]=1; } } } } return true; } int main(){ cin>>n>>m>>k; int i; memset(h,-1,sizeof h); for(i=1;i<=m;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); if(a>b) swap(a,b); add(a,b,c); } for(i=1;i<=k;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); if(a>b) swap(a,b); add(b,a,-c); } for(i=1;i<n;i++){ add(i+1,i,0); } if(!spfa(n)){ cout<<-1<<endl; } else{ spfa(1); if(dis[n]==inf) cout<<-2<<endl; else cout<<dis[n]<<endl; } }
没有人不辛苦,只有人不喊疼