1. 程式人生 > >【poj3169 Layout】【差分約束】【Bellman-Ford】

【poj3169 Layout】【差分約束】【Bellman-Ford】

【連結】

【題意】

有N個點,其中有ml個限制條件:點a,點b,的最長距離為d,有md個限制條件,點a,點b,的最短距離為d;點按序號順序排,求第一個點到最後一個點的最長距離。

【思路】

記錄第i號牛的位置d[i],首先,牛是按標號排序的,有d[i]<=d[i+1].

對於關係好的牛之間的最大距離,有d[AL]+DL<=d[BL].同樣有:d[AD]+DD<=d[BD].

問題轉化為,在滿足三類不等式條件下的d[N]-d[1]的最大值

不等式特點:所有式子兩邊都只出現了一個變數。

最短路問題中:記從點s出發,到各個頂點v的最短路的距離為d[v].因此,對於每條權值為w的邊e=(v,u),都有d(v)+w>=d(u).

反之,對於每條滿足不等式的d中,d(v)-d(s)的最大值就是從s-v的最距離。

【程式碼】

#include<cstdio>
#include<math.h>
#include<string>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 1e5 + 6;
const int inf = 0x3f3f3f3f;

int d[maxn];
struct node1 {
	int a,b,c;
}k1[maxn];
struct node2 {
	int a, b, c;
}k2[maxn];

int main() {
	//freopen("binary.in", "r", stdin);
	//freopen("binary.out", "w", stdout);
	memset(d, inf, sizeof(d));
	d[0] = 0;
	int n, ml, md;
	scanf("%d%d%d", &n, &ml, &md);
	//A B D:B-A>=D
	for (int i = 0; i < ml; i++) {
		int a, b, d;
		scanf("%d%d%d", &k1[i].a, &k1[i].b, &k1[i].c);
	}
	//A B D:B-A<=D
	for (int i = 0; i < md; i++) {
		int a, b, d;
		scanf("%d%d%d", &k2[i].a, &k2[i].b, &k2[i].c);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if(d[j+1]<inf)d[j] = min(d[j], d[j + 1]);
		}
		for (int j = 0; j < ml; j++) {
			if(d[k1[j].a-1]<inf)
			d[k1[j].b - 1] = min(d[k1[j].b - 1], d[k1[j].a - 1] + k1[j].c);
		}
		for (int j = 0; j < md; j++) {
			d[k2[j].a - 1] = min(d[k2[j].a - 1], d[k2[j].b - 1] - k2[j].c);
		}
	}
	if (d[0] < 0)printf("-1\n");
	else if (d[n - 1] == inf)printf("-2\n");
	else printf("%d\n", d[n - 1]);
}