题目大意
解题思路
给定不等式组,然后要求其中两个元素相差(比如C-A
)的最大值。这可以等价为求最短路问题。因为任何一条
的路都对应着一个或者多个不等式中隐含的关于C-A
的约束。具体理解可以见下图:
一般解题步骤:
- (1)建图: 对每一个形如 的不等式,构造一条 、长度为 的有向边。
- (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)贝尔曼福特算法存的是边,不是邻接表。