zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    iptables一个包过滤防火墙实例
    www的iptables实例
    iptables单个规则实例
    iptables [-j target/jump] 常用的处理动作
    iptables [match] 常用封包匹配参数
    iptables command 常用命令列表
    iptables [-t table] 指定规则表
    iptablesIP规则的保存与恢复
    iptables在我们的网络机房实现NAT共享上网
    iptables典型NAT上网
  • 原文地址:https://www.cnblogs.com/Gaxc/p/10201553.html
Copyright © 2011-2022 走看看