bzoj1731: [Usaco2005 dec]Layout 排队布局(差分约束系统)

原题链接

题目描述:当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些。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号奶牛间可能的最大距离。

输入格式:第一行:三个整数n,Ml,Md,用空格分隔。
第2 ~ Ml+1行:每行三个整数a,b,c。表述a与b之间的距离应≤c。保证a < b。
第Ml+2 ~ ML+Md+1行:每行三个整数a,b,c。表述a与b之间的距离应≥D 。保证a < b。

输出格式:一行,一个整数。如果没有合法方案,输出 -1. 如果有合法方案,但 1 号奶牛可以与 N 号奶牛相距无穷远,输出 -2. 否则,输出 1 号奶牛与 N 号奶牛间的最大距离。

输入样例
4 2 1
1 3 10
2 4 20
2 3 3

输出样例
27

解析:一道差分约束的经典题。
   由题意,可知要求\(d_b-d_a≤D,d_d-d_c≥D,d_{i+1}-d_{i}≥0\)
   即\(d_b-d_a≤D,d_c-d_d≤D,d_{i}-d_{i+1}≤0\)
   所以建边后有spfa跑一次最短路即可。
   若存在负环,则输出-1。若无法连通,则输出-2。

代码如下:

#include<cstdio>
#include<queue>
using namespace std;
 
const int maxn = 1e5 + 5 ;
int n, l, d, dis[maxn], vis[maxn], cnt[maxn];
int nxt[maxn], hed[maxn], to[maxn], val[maxn], tot;
queue <int> que;
 
int read(void) {
    char c; while (c = getchar(), c < '0' || c > '9'); int x = c - '0';
    while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; return x;
}
 
void add(int x, int y, int v) {
    nxt[++ tot] = hed[x]; hed[x] = tot; to[tot] = y; val[tot] = v;
}
 
int spfa(void) {
      for (int i = 1; i <= n; ++ i) dis[i] = 2e9;
    vis[1] = 1; dis[1] = 0; cnt[1] = 1; que.push(1);
      while (!que.empty()) {
        int u = que.front(); vis[u] = 0; que.pop();
          for (int i = hed[u]; i ; i = nxt[i]) {
            int v = to[i];
              if (dis[v] > dis[u] + val[i]) {
                dis[v] = dis[u] + val[i];
                if (!vis[v]) {
                  if (++ cnt[v] > n) return -1;
                  vis[v] = 1; 
                  que.push(v);
                }
              }
          }
      }
    if (dis[n] == 2e9) return -2;
    return dis[n];
}
 
int main() {
    n = read(); l = read(); d = read();
      for (int i = 2; i <= n; ++ i) add(i, i - 1, 0);
      for (int i = 1; i <= l; ++ i) {
        int x = read(), y = read(), v = read();
        add(x, y, v);
      }
      for (int i = 1; i <= d; ++ i) {
        int x = read(), y = read(), v = read();
        add(y, x, -v);
      }
    printf("%d", spfa());
    return 0;
}
posted @ 2018-12-31 10:52  Gax_c  阅读(121)  评论(0编辑  收藏  举报