挑战程序设计竞赛: Layout

题目大意

在这里插入图片描述

解题思路

给定不等式组,然后要求其中两个元素相差(比如C-A)的最大值。这可以等价为求最短路问题。因为任何一条 A C A\to C 的路都对应着一个或者多个不等式中隐含的关于C-A的约束。具体理解可以见下图:
from https://www.cnblogs.com/genius777/p/9163103.html一般解题步骤:

  • (1)建图: 对每一个形如 A V d A - V \leq d 的不等式,构造一条 V A V \to A 、长度为 d d 的有向边。
  • (2)求C-A最大值即为A到C最短路
  • (3)若有负环,则无解。(有负环则无最短路)
  • (3)若为INF, 则任意。(即C-A的最大值无限长)

代码

#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;
const int MAX = 1005;
const int MAXE = 10000*2+5;
const int inf = 1<<20;
struct Edge
{
    int s;
    int t;
    int w;
}G[MAXE];
int d[MAX];
int N, ML, MD;
int cnt;
int bemft(int v)
{
    for(int i=0; i<=N; i++)
        d[i] = inf;
    d[v] = 0;
    for(int i=1; i<=N; i++)
    {
        int update = 0;
        for(int e=0; e<cnt; e++)
        {
            int from = G[e].s;
            int to = G[e].t;
            int cost = G[e].w;
            if(d[to] > d[from] + cost)
            {
                d[to] = d[from] + cost;
                update = 1;
            }
        }
        if(!update)
        {
            if(d[N] == inf)
                return -2;
            return d[N];
        }
        if(i >= N-1)
            return -1;
    }
}
int main()
{
    cnt = 0;
    scanf("%d%d%d", &N, &ML, &MD);
    for(int i=1; i<=N-1; i++)
    {
        G[cnt].s = i+1;
        G[cnt].t = i;  // d[i+1] >= d[i]   --> d[i+1] + 0 >= d[i]
        G[cnt++].w = 0;
    }

    int a, b, w;
    while(ML--)
    {
        scanf("%d%d%d", &a, &b, &w); // d[b] - d[a] <= w   --> d[b] <= w + d[a]
        G[cnt].s = a;
        G[cnt].t = b;
        G[cnt++].w = w;
    }
    while(MD--)
    {
        scanf("%d%d%d", &a, &b, &w);  // d[b] - d[a] >= w  --> d[b] - w >= d[a]
        G[cnt].s = b;
        G[cnt].t = a;
        G[cnt++].w = -w;
    }
    int ans = bemft(1);

    cout << ans << endl;
    return 0;
}

知识点

  • 贝尔曼福特算法若没有负环,最多更新|V|-1次。
  • 牢记差分约束系统和最短路之间的转换。包括(1)构图.(2)求差的最大值是求最短路。(3)贝尔曼福特算法存的是边,不是邻接表。

猜你喜欢

转载自blog.csdn.net/Wangpeiyi9979/article/details/93708883