题意
有n头牛,编号是1~n,他们按编号顺序排成一排,这些牛之间有关系好的和关系坏的,关系好的ml对牛,给出他们之间的距离的最大值,关系差的md对牛,给出他们之间距离的最小值。牛可以站在同一个位置上。在满足这些条件的情况下,求编号为1的牛和n的牛距离的最大值。
思路
假如第i头牛的位置为dist[i],那么必定有dist[i] <= dist[i + 1],然后有最大距离限制,dist[a[i]] + dl[i] <= dist[b[i]],最小距离限制dist[a[i]] + dd[i] >= dist[b[i]],这些关系都可以转化成a - b <= c的形式,我们建一条b->a的权值为c的边,形成的这个图,求最短路即是最长距离,(证明:a - b <= x1, b - c <= x2, a - c <= x3, a - c <= min(x1 + x2, x3))。
代码
#include <cstdio>
#include <iostream>
using namespace std;
const int kMaxn = 10000 + 10;
const int kInf = 0x3f3f3f3f;
struct Edge {
int u,v;
int w;
} g[kMaxn * 3];
int dist[kMaxn];
int n,ml,md,top;
void Init() {
top = 0;
}
void AddEdge(int a, int b, int d) {
top++;
g[top].u = a;
g[top].v = b;
g[top].w = d;
}
void Bellman_Ford(int s, int t) {
for(int i = 1; i <= n; i++)
dist[i] = kInf;
dist[s] = 0;
for(int k = 1; k < n; k++) {
for(int i = 1; i <= top; i++) {
if(dist[g[i].u] != kInf && dist[g[i].u] + g[i].w < dist[g[i].v])
dist[g[i].v] = dist[g[i].u] + g[i].w;
}
}
}
int main() {
while(~scanf("%d %d %d", &n, &ml, &md)) {
int a,b,d;
Init();
for(int i = 1; i <= ml; i++) {
scanf("%d %d %d", &a, &b, &d);
AddEdge(a, b, d);
}
for(int i = 1; i <= md; i++) {
scanf("%d %d %d", &a, &b, &d);
AddEdge(b, a, -d);
}
//printf("%d\n", top);
for(int i = 1; i < n; i++)
AddEdge(i + 1, i, 0);
//printf("%d\n", top);
Bellman_Ford(1, n);
if(dist[1] < 0)
printf("-1\n");
else if(dist[n] == kInf)
printf("-2\n");
else
printf("%d\n", dist[n]);
}
return 0;
}