• 【差分约束】Layout


    Layout
    TimeLimit: 1000MS   MemoryLimit: 65536K
         

    Description

    Like everyone else, cows like to stand close to their friends when queuing for feed. FJ has N (2 <= N <= 1,000) cows numbered 1..N standing along a straight line waiting for feed. The cows are standing in the same order as they are numbered, and since they can be rather pushy, it is possible that two or more cows can line up at exactly the same location (that is, if we think of each cow as being located at some coordinate on a number line, then it is possible for two or more cows to share the same coordinate).

    Some cows like each other and want to be within a certain distance of each other in line. Some really dislike each other and want to be separated by at least a certain distance. A list of ML (1 <= ML <= 10,000) constraints describes which cows like each other and the maximum distance by which they may be separated; a subsequent list of MD constraints (1 <= MD <= 10,000) tells which cows dislike each other and the minimum distance by which they must be separated.

    Your job is to compute, if possible, the maximum possible distance between cow 1 and cow N that satisfies the distance constraints.

    Input

    Line 1: Three space-separated integers: N, ML, and MD.

    Lines 2..ML+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at most D (1 <= D <= 1,000,000) apart.

    Lines ML+2..ML+MD+1: Each line contains three space-separated positive integers: A, B, and D, with 1 <= A < B <= N. Cows A and B must be at least D (1 <= D <= 1,000,000) apart.

    Output

    Line 1: A single integer. If no line-up is possible, output -1. If cows 1 and N can be arbitrarily far apart, output -2. Otherwise output the greatest possible distance between cows 1 and N.

    Sample Input

    4 2 1
    1 3 10
    2 4 20
    2 3 3

    Sample Output

    27

    Hint

    Explanation of the sample:

    There are 4 cows. Cows #1 and #3 must be no more than 10 units apart, cows #2 and #4 must be no more than 20 units apart, and cows #2 and #3 dislike each other and must be no fewer than 3 units apart.

    The best layout, in terms of coordinates on a number line, is to put cow #1 at 0, cow #2 at 7, cow #3 at 10, and cow #4 at 27.

    题目大意
    农夫约翰养了N头牛,编号分别是1到N。现在,它们要进食,按照编号顺序排成了一排。在它们之间有一些牛关系比较好,所以希望彼此之间不超过一定距离,也有一些牛关系比较不好,所以希望彼此之间至少要满足某个距离。此外,牛的性格比较犟,所以有可能有多头牛挤在同一个位置上。给出了ML个关系好的牛的信息(AL,BL,DL)以及MD个关系不好的牛的信息(AD,BD,DD)。这表示的是牛AL与牛BL之间的最大距离DL和牛AD与牛BD之间的最小距离DD。在满足这些条件的排列方法中,求1号牛和N号牛之间的最大距离。如果不存在任何一种排列方法满足条件则输出-1。无限大的情况输出-2。
     
    分析
    首先由经典的最短路问题引出差分约束,
    记从起点s出发,到各个顶点v的最短距离为d(v)。因此,对于每条权值为w的边e=(v,u),都有d(v)+w>=d(u)成立,
    像这样所有式子的两边都只出现了1个变量的特殊形式叫差分约束
    在满足全部这些约束不等式的d中,d(s)+从s到v的最短距离>=d(v),即d(v)-d(s)<=从s到v的最短距离,
    所以d(v)-d(s)的最大值就是从s到v的最短距离。
     
    再回到该问题,
    设,第i号牛的位置是d[i]。
    通过分析牛的关系和距离可得,
    ①牛是按照编号顺序排序,d[i]<=d[i+1]
    ②每对关系好的牛之间的最大距离限制,是d[AL]+DL>=d[BL]
    ③每对关系不好的牛之间的最小距离限制,是d[AD]+DD<=d[BD]
    得到差分约束,对应着最短路问题得,
    ①变形得,d[i+1]+0>=d[i],对应着从顶点i+1向顶点连一条权值为0的边。
    ②,③同①可得到对应的边。
    问题是求1号牛和N号牛之间的最大距离。即d[N]-d[1]的最大值,即在最短路问题中的从源点到N的最短距离。
     
    因为可能会出现牛与牛之间的距离是负数时,才能满足所有关系好与不好的牛的情况,然而距离不可能是负数,所以要检测负权边,所以要用Bellma-Ford算法,不能用Dijkstra算法。
     
    参考代码
    参考自《挑战程序设计 第二版》
    #include <iostream>
    #include <cstdio>
    const int MAX_ML=10001,MAX_MD=10001,MAX_N=10001,INF=1e9;
    
    using namespace std;
    
    int N,ML,MD;
    int AL[MAX_ML],BL[MAX_ML],DL[MAX_ML];
    int AD[MAX_MD],BD[MAX_MD],DD[MAX_MD];
    
    int d[MAX_N];//最短距离
    int main()
    {
        scanf("%d%d%d",&N,&ML,&MD);
        for(int i=0;i<ML;i++){
            scanf("%d%d%d",&AL[i],&BL[i],&DL[i]);
        }
        for(int i=0;i<MD;i++){
            scanf("%d%d%d",&AD[i],&BD[i],&DD[i]);
        }
        fill(d,d+N,INF);
        d[0]=0;
        ///d[v]+w>=d[u],Bellman-Ford算法
        for(int k=0;k<N;k++){
            ///d[i+1]+0>=d[i]
            for(int i=0;i+1<N;i++){
                if(d[i+1]<INF)d[i]=min(d[i],d[i+1]);
            }
            ///d[AL]+DL>=d[BL]
            for(int i=0;i<ML;i++){
                if(d[AL[i]-1]<INF){
                    d[BL[i]-1]=min(d[BL[i]-1],d[AL[i]-1]+DL[i]);
                }
            }
            ///d[BD]-DD>=d[AD]
            for(int i=0;i<MD;i++){
                if(d[BD[i]-1]<INF){
                    d[AD[i]-1]=min(d[AD[i]-1],d[BD[i]-1]-DD[i]);
                }
            }
        }
    
        int res=d[N-1];
        //判断是否存在负权边
        if(d[0]<0){
            res=-1;
        }
        else if(res==INF){
            res=-2;
        }
        printf("%d
    ",res);
        return 0;
    }
     
     
     
     
     
  • 相关阅读:
    EcFinal游记
    简要介绍补码的原理
    【SCOI2007】降雨量
    【ecfinal2019热身赛】B题
    【HAOI2011】problem a
    20200301(ABC)题解 by李旭晨
    20200228(ABC)题解 by 马鸿儒
    20200220(C)题解 b刘存
    20200225(DEF)题解 by 马鸿儒
    20200224(ABC)题解 by 马鸿儒
  • 原文地址:https://www.cnblogs.com/LuRenJiang/p/7434558.html
Copyright © 2020-2023  润新知