题意:
从1到n,n个数,从左向右依次排列。给定两种形式的约束条件:
1. xi 与 yi 的最大距离为 dk
2. xi 与 yi 的最小距离为 dk
问满足这些限定条件的情况下,数1和n的最大距离是多少?(若约束条件相互矛盾则输出-1,若最大距离可以为无穷大则输出-2)知识补充:
- 差分约束系统的概念:由n个变量和m个约束条件(实数)组成,且都是形如:
xi−yj≤bk(x,y为变量,b为实数)的形式。
- 用Bellman-Ford算法求解差分约束系统:由于最短路三角不等式: d[v]−d[u]≤e[u,v] 与差分约束的不等式形式一样,故构建j到i长度为bk的边来建成一个图,由于可能存在负边所以用Bellman-Ford算法来求解最短路,最终得到的d[i]数组是满足该差分约束系统的一个可行解。
- 注:若{d[1], d[2], ….. ,d[n]}是差分约束系统的一个可行解,那么{d[1] + x, d[2] + x, ….., d[n] + x}也是可行解。
- 关于d[n]数组的初始化:如果将原点s到每个顶点的距离都设置为0,最后求出来的可行解满足这些点相互之间距离最小。如果将其中一个点设为起点,其它点的距离都设置设为INF,那么最终求出来的可行解,满足该起点,到其它每个点相互之间的距离最大。
思路:
- 差分约束系统的概念:由n个变量和m个约束条件(实数)组成,且都是形如:
题目为有三个限制条件的差分约束系统,即:
d[i]−d[i+1]≤0d[BL]−d[AL]≤DLd[AD]−d[BD]≤DD根据这三个不等式建立图,这里核心难点是:为什么d[n] - d[1](即起点1到终点n的最短距离)就是对于约束条件下,1到n的最长距离?(这里尚未思考明白…..)
代码(代码中的Bellman-Ford算法经过防止负圈优化):
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
const int INF = 0x3fffffff;
struct edge{int from, to, cost;}E[100009];
int v, n, m, size;
void input(void) {
int x, y, z;
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &x, &y, &z);
E[size++] = (edge){x - 1, y - 1, z};
}
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &x, &y, &z);
E[size++] = (edge){y - 1, x - 1, -z};
}
}
int bellman_ford(void) {
int d[v];
fill(d, d + v, INF);
d[0] = 0;
for (int k = 0; k < v; k++) { //由于可能存在负圈会无限更新的情况要注意设置更新次数上限为顶点个数。
bool update = false;
for (int i = 0; i < size; i++) {
if(d[E[i].to] > d[E[i].from] + E[i].cost && d[E[i].from] < INF) {
update = true;
d[E[i].to] = d[E[i].from] + E[i].cost;
}
}
if(!update) break;
}
if(d[0] < 0) return -1;
if(d[v - 1] == INF) return -2;
return d[v - 1];
}
int main(void)
{
while (~scanf("%d%d%d", &v, &n, &m)) {
size = 0;
for (int i = 0; i < v - 1; i++) {
E[size++] = (edge){i + 1, i, 0}; //这个形式很有趣
}
input();
printf("%d\n", bellman_ford());
}
return 0;
}