题目描述
有n头牛,之间有两种限制,一种是距离不超过x,另一种距离不小于x,求1号和n号的最大距离,若不存在方案则输出-1,距离可以无穷大输出-2;
2≤N≤1000,两种限制1≤ML, MD≤104
题解
差分约束裸题;
要求最大距离,所以最短路?因为好像最短路是从最大值减小直到满足条件,所以最后一定是最大值。
这道题要注意的地方就是负环可能和1不连通,所以只从1跑spfa可能判不到负环。
为了判负环就只有建虚拟点向所有点连边,从虚拟点跑spfa判负环。
最后从1跑spfa求最短路,如果dis[n]没被更新,就说明两个没有约束条件。

#include<bits/stdc++.h> using namespace std; #define ll long long const int oo=2000000000; const int maxn=1005; const int maxm=21005; int n,m1,m2; int head[maxn],cnt; struct edge{ int y,next; ll val; }e[maxm]; template<class T>inline void read(T &x){ x=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} } void add(int x,int y,ll z){ e[++cnt]=(edge){y,head[x],z}; head[x]=cnt; } queue<int> q; ll dis[maxn],cx[maxn]; bool vis[maxn]; void spfa(int s){ while(!q.empty()) q.pop(); for(int i=0;i<=n;i++) dis[i]=oo,cx[i]=0,vis[i]=false; dis[s]=0;vis[s]=true;cx[s]=1; q.push(s); while(!q.empty()){ int x=q.front(); q.pop(); vis[x]=false; for(int i=head[x];i;i=e[i].next){ int y=e[i].y; if(dis[y]>dis[x]+e[i].val){ dis[y]=dis[x]+e[i].val; if(!vis[y]){ q.push(y);vis[y]=true; if(++cx[y]>n) {printf("-1");exit(0);} } } } } } int main(){ read(n);read(m1);read(m2); for(int i=1;i<=m1;i++){ int x,y; ll z; //dis[y]-dis[x]<=z //dis[y]<=dis[x]+z read(x);read(y);read(z); add(x,y,z); } for(int i=1;i<=m2;i++){ int x,y; ll z; //dis[y]-dis[x]>=z //dis[x]<=dis[y]-z read(x);read(y);read(z); add(y,x,-z); } for(int i=1;i<=n;i++) add(0,i,0); spfa(0); spfa(1); printf("%lld",dis[n]==oo ? -2 : dis[n]); }