【USACO2005Dec】奶牛的站位 Layout

题目描述

有 N 头奶牛正在排队,它们的编号为 1 到 N,约翰要给它们安排合适的排队位置,满足以下条 件:

• 首先,所有奶牛要站在一条直线上。由于是排队,所以编号小的奶牛要靠前,不能让编号大的 奶牛插队。但同一个位置可以容纳多头奶牛,这是因为它们非常苗条的缘故

• 奶牛喜欢和朋友靠得近点。朋友关系有 F 对,其中第 Ai 头奶牛和第 Bi 头奶牛是第 i 对朋友, 它们的距离不能超过 Ci

• 奶牛还要和讨厌的同类保持距离。敌对关系有 E 对,其中第 Xi 头奶牛和第 Yi 头奶牛是第 i 对 敌人,它们的距离不能少于 Zi

你能否帮助约翰找到一个合理的站位方法,满足所有奶牛的要求,而且让 1 号奶牛和 N 号奶牛间的 距离尽量大?

输入格式

• 第一行:三个整数 N,F 和 E,2 ≤ N ≤ 1000, 1 ≤ F;E ≤ 10000

• 第二行到第 F + 1 行:第 i + 1 行有三个整数 Ai,Bi 和 Ci,1 ≤ Ai,Bi ≤ N; 1 ≤ Ci ≤ 10^6

• 第 F + 2 行到第 F + E + 1 行:第 i + F + 1 行有三个整数 Xi,Yi 和 Zi,1 ≤ Xi,Yi ≤ N; 1 ≤Zi ≤ 10^6

输出格式

• 单个整数:如果不存在满足所有条件的安排,输出 −1;如果 1 号奶牛和 N 号奶牛的距离可以 任意大,输出 −2;否则输出 1 号奶牛和 N 号奶牛的最大距离

样例输入

4 2 1

1 3 10

2 4 20

2 3 3

样例输出

27

解释

一号奶牛站在坐标 0,二号奶牛站在坐标 7,

三号奶牛站在坐标 10,四号奶牛站在坐标 27

题解

比较明显的差分约束系统吧。

根据题目条件很容易得出两个不等式

        min(Ai,Bi)-max(Ai,Bi)>= -Ci

        max(Xi,Yi)-min(Xi,Yi)>= Zi

根据差分约束系统原理,从min(Ai,Bi)向max(Ai,Bi)引一条权值为Ci的有向边,从max(Xi,Yi)向min(Xi,Yi)引一条权值为Zi的有向边,然后SPFA求最短路就可以了。

有时为了防止建成的图不连通,常构造一个节点,从这个节点向每个节点连一条边,本题可以不这样。

dis数组初始化为无穷大,走最短路时,如果有负环,就不存在满足所有条件的安排,输出 −1;如果走完最短路dis[n]还是无穷大,1 号奶牛和 N 号奶牛的距离可以 任意大,输出 −2;不满足以上条件的,直接输出dis[n]。

#include <cstdio>
const int N=2005;
struct node{
    int id,nex,u,w;
}; 
node g[40005];
int fir[1005],num,dis[1005],q[2005],cnt[1005],n;
bool vis[1005];
int min(int x,int y)
{
    return x<=y?x:y;
}
int max(int x,int y)
{
    return x>=y?x:y;
}
void add(int x,int y,int z)
{
    g[++num].u=y;  g[num].w=z;  g[num].nex=fir[x];  fir[x]=num;
}
void SPFA()
{
    int t=1,h=0,i,j,k,v;
    for (i=2;i<=n;i++)
      dis[i]=1e9;
    q[1]=1;  vis[1]=true;
    while (h!=t)
    {
        h=(h+1)%N;
        for (k=fir[q[h]];k;k=g[k].nex)
           if (dis[q[h]]+g[k].w<dis[g[k].u])
          {
            dis[g[k].u]=dis[q[h]]+g[k].w;
            if (!vis[g[k].u])
            {
                vis[g[k].u]=true;
                t=(t+1)%N;
                q[t]=g[k].u;
                cnt[g[k].u]++;
                if (cnt[g[k].u]>n)
                {
                    dis[n]=-1;
                    return;
                } 
            }
              
          }
        vis[q[h]]=false;  
    }  
    return;
}
int main()
{
    int F,E,A,B,C,i,j;
    scanf("%d%d%d",&n,&F,&E);
    for (i=1;i<=F;i++)
         scanf("%d%d%d",&A,&B,&C),
      add(min(A,B),max(A,B),C);

    for (i=1;i<=E;i++)
      scanf("%d%d%d",&A,&B,&C),
      add(max(A,B),min(A,B),-C);

    /*  for (i=1;i<=n;i++)
           add(0,i,0);   */
    SPFA();
    printf("%d",dis[n]!=1e9?dis[n]:-2);
    return 0;  
}

 

原文地址:https://www.cnblogs.com/rabbit1103/p/8393559.html