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

本文探讨了一种涉及牛群间距离限制的算法问题,通过分析点间的最大与最小距离约束,利用迭代和优化策略,求解首尾两点间可能的最大距离。文章详细介绍了算法思路,包括变量初始化、条件判断及迭代更新过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【链接】

http://poj.org/problem?id=3169

【题意】

有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]);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值