POJ No.3169 Layout

将已知条件抽象:

d[i+1] + 0  >=  d[i]

d[AL]+DL  >=  d[BL]

d[BD]+(-DD)  >=  d[AD]

 

问题为:

满足以上诸多条件的情况下,求出d[n] – d[1]的最大值。

即求d[1]+ MAX>=d[n] 中MAX的值。

 

 分析:

1)d[i]+x >= d[j]  d[k]+y>= d[i] 则有d[k]+(x+y)>=d[i]

符合递推特性

 

2)d[m]+x>=d[n]

如若d[n]可由多个d[m]{m属于1到N}转移得到,又由于各个方程需要同时满足,故取各个d[n]中的最小值

 

以上分析可得

d[n] = min{d[m] + x为两者差}

 

具体思路:

将方程以图论模型中的边表示

struct link

{

       int from;

       int to;

       int cost;

};    //  from + cost >=  to

 

 转化为最短路问题求解

 

算法主体思想:

 

不断由边更新每个点的值,如有解则可在 点数*边数时间,即O(N*(N+ML+MD))内完成所有点值的更新。



#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define INF 1e9

using namespace std;

struct LL
{
	int from;
	int to;
	int cost;
}; // d[from] + cost >= d[to]

LL link[20010];
int d[1010];

int main()
{
	int num_node, num_link1, num_link2;
	scanf("%d %d %d", &num_node, &num_link1, &num_link2);
	fill(d, d + num_node, INF);
	d[0] = 0;

	// preparing for graph
	for (int i = 0; i < num_link1; ++i)
	{
		int AL, BL, DL; // d[AL] + DL >= d[BL]
		scanf("%d %d %d", &AL, &BL, &DL);
		link[i].from = AL-1;
		link[i].to = BL-1;
		link[i].cost = DL;
	}
	for (int i = num_link1; i < num_link1 + num_link2; ++i)
	{
		int AD, BD, DD; // d[BD] + (-DD) >= d[AD]
		scanf("%d %d %d", &AD, &BD, &DD);
		link[i].from = BD-1;
		link[i].to = AD-1;
		link[i].cost = -DD;
	}

	for (int i = 0; i < num_node; ++i)
	{
		for (int j = 0; j+1 < num_node; ++j)
			if(d[j+1]<INF)
				d[j] = min(d[j], d[j+1]);

		for (int j = 0; j < num_link1+num_link2; ++j)
			if(d[link[j].from]<INF)
				d[link[j].to] = min(d[link[j].to], d[link[j].from]+link[j].cost);
	}

	int res = d[num_node-1];
	if(d[0] < 0)
		res = -1;
	else if(res == INF)
		res = -2;

	printf("%d\n", res);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值