BZOJ-1731: [Usaco2005 dec]Layout 排队布局

[文章目录]

Description

奶牛喜欢和它们的朋友站得靠近些。FJ有N(2<=N<=1000)头奶牛,编号从1到N,沿一条直线站着等候喂食。奶牛排在队伍中的顺序和它们的编号是相同的。因为奶牛相当苗条,所以可能有两头或者更多奶牛站在同一位置上。即使说,如果我们想象奶牛是站在一条数轴上的话,允许有两头或更多奶牛拥有相同的横坐标。一些奶牛相互间存有好感,它们希望两者之间的距离不超过一个给定的数L。另一方面,一些奶牛相互间非常反感,它们希望两者间的距离不小于一个给定的数D。给出ML条关于两头奶牛间有好感的描述,再给出MD条关于两头奶牛间存有反感的描述。(1<=ML,MD<=10000,1<=L,D<=1000000)你的工作是:如果不存在满足要求的方案,输出-1;如果1号奶牛和N号奶牛间的距离可以任意大,输出-2;否则,计算出在满足所有要求的情况下,1号奶牛和N号奶牛间可能的最大距离。

差分约束。
建模,先判断是否有负环,输出-1。再从n跑最长路,如果1的最长路为初始值,说明n可以无限大,输出-2,反之,输出inf-dis[1]

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int n,ml,md;
int head[1100],to[30000],nxt[30000],f[30000],cnt;
inline void add(int x,int y,int z)
{
    to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt; f[cnt]=z;
}
int dis[1100];
bool vis[1100];
int spfa()
{
    static int q[4200];
    int l=1,r=n,x; dis[n]=inf;
    for(int i=n;i;--i) q[n-i+1]=i,vis[i]=1;
    while(l<=r)
    {
        x=q[l++]; vis[x]=0;
        for(int i=head[x];i;i=nxt[i]) if(dis[to[i]]<dis[x]+f[i])
        {
            dis[to[i]]=dis[x]+f[i];
            if(!vis[to[i]])
            {
                q[++r]=to[i],vis[to[i]]=1;
                if(r==4000) return -1;
            }
        }
    }
    memset(dis,0,sizeof dis); dis[n]=inf;
    l=r=1; q[1]=n; vis[n]=1;
    while(l<=r)
    {
        x=q[l++]; vis[x]=0;
        for(int i=head[x];i;i=nxt[i]) if(dis[to[i]]<dis[x]+f[i])
        {
            dis[to[i]]=dis[x]+f[i];
            if(!vis[to[i]])
            {
                q[++r]=to[i];
                vis[to[i]]=1;
            }
        }
    }
    if(dis[n]-dis[1]==inf) return -2;
    return dis[n]-dis[1];
}
int main()
{
    scanf("%d%d%d",&n,&ml,&md);
    for(int i=1;i<n;++i) add(i,i+1,0);
    int x,y,z;
    while(ml--)
    {
        scanf("%d%d%d",&x,&y,&z);
        if(x>y) swap(x,y);
        add(y,x,-z);
    }
    while(md--)
    {
        scanf("%d%d%d",&x,&y,&z);
        if(x>y) swap(x,y);
        add(x,y,z);
    }
    printf("%d",spfa());
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注