[USACO05DEC] 布局

题目描述

有n头牛,之间有两种限制,一种是距离不超过x,另一种距离不小于x,求1号和n号的最大距离,若不存在方案则输出-1,距离可以无穷大输出-2;

2N1000,两种限制1MLMD104

题解

差分约束裸题;

要求最大距离,所以最短路?因为好像最短路是从最大值减小直到满足条件,所以最后一定是最大值。

这道题要注意的地方就是负环可能和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]);
}
View Code
posted @ 2019-07-23 21:46  _JSQ  阅读(137)  评论(0编辑  收藏  举报