poj 3169 Layout(最短路 · Bellman-Ford)

题目链接:http://poj.org/problem?id=3169

Layout

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.

这题的最短路径算法还是比较抽象的,不容易想出。

记第 i 号牛的位置是 d[i]。按照题目的叙述,牛按顺序排列,且可以站在同一个位置,则有:d[i] <= d[i+1]。

对于关系好的牛而言有:d[A] + D >= d[B]。

对于关系差的牛而言有:d[A] + D <= d[B]。

那么考虑下最短路径的特征,记起点为s,到各个顶点的最短距离为d(v)。因此对于每条权重为w的边e=(v,u),

都有:d[v]+e >= d[u]。等号仅在该边为最短路径上的边时取到。

当对所有的这些约束不等式都满足时,d(v)-d(s)的最大值就是从s到v的最短距离。注意这里是取最大值。

把原问题和最短路特征一比较即可发现,原问题是可以转换成最短路问题求解的。

对于第一种情况,就是d[i+1] + 0 >= d[i]。即从顶点 i+1 向顶点 i 连一条权值为 0 的边。

对于第二种情况,就是d[A] + D >= d[B]。即从顶点 A 向顶点 B 连一条权值为 B 的边。

对于第三种情况,就是d[B] – D >= d[A]。即从顶点 B 向顶点 A 连一条权值为 -D 的边。

所以最终问题转换为了 d[N] – d[1] 的最大值,对应于顶点1到顶点N的距离。

由于图中存在负边。无法使用Dijkstra算法只能使用Bellman-Ford算法。复杂度为O(N(N+ML+MD))。

#include <iostream>
#include <cstdio>

using namespace std;

const int INF = 0x3f3f3f3f;
const int MAX_N = 1010;
const int MAX_ML = 10010;
const int MAX_MD = 10010;

int n, ml, md;

int d[MAX_N];// 第i头牛的最终位置 也是最短距离
int AL[MAX_ML], BL[MAX_ML], DL[MAX_ML];
int AD[MAX_MD], BD[MAX_MD], DD[MAX_MD];

void solve() {
    fill( d, d+n, INF );
    d[0] = 0;

    for ( int k = 0 ; k < n ; ++ k ) {
        // 从i+1到i的权值为0
        for ( int i = 0 ; i+1 < n ; ++ i ) {
            if ( d[i+1] < INF ) d[i] = min(d[i], d[i+1]);
        }

        // 从AL到BL的权值为DL
        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]);
            }
        }

        // BD到AD的权值为-DD
        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\n", res );
}

int main(int argc, char const *argv[])
{
    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] );
    }

    solve();

    return 0;
}

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/hopyGreat/article/details/80380511
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞