Currency Exchange POJ - 1860 单源最短路 Bellman_Ford

传送门

题目大意: 有n中货币, m个兑换货币点, 每个兑换点可以两种货币相互兑换, 每个货币点有六个数字描述: a b rate1 com1 rate2 com2 表示 a b两种货币可以相互兑换, a货币兑换b货币的 手续费为com1 比率为rate1 如果反过来兑换则为 rate2 和com2. 例如: A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。 问题是s货币通过兑换能否增加, (注意最终货币的形式还是s).

题目分析: 最终要兑换成s货币, 那么不管怎样兑换, 一定能形成一个回路, 从s出发, 最终回到s, 并且s货币的数量要增加, 那么就可以认为这个回路是图上的一个正权回路. 我们以货币为顶点 兑换比率和手续费为边 建图. 不管更新顶点的最大权值(也就是货币的数量), 如果到了s的时候, s点的权重值增加了, 证明存在正权回路, 也就是可以增加货币.反之则不能, 因此用Bellman_Ford算法.

代码:

#include <iostream>
#include <cstdio>


using namespace std;

struct edge
{
	int a, b;
	double rate, com;
}E[220];
int numE;
double d[120]; //d[s]表示最多可以获得d[s]个s货币


bool Bellman_Ford(int s, double v)
{
	for(int i=0; i<120; ++i) d[i] = 0;
	d[s] = v;
	while(true)
	{
		bool update = false;
		for(int i=0; i<numE; ++i)
		{
			int a = E[i].a;
			int b = E[i].b;
			if((d[a] - E[i].com)*E[i].rate > d[b])
			{
				if(b == s) return true;
				update = true;
				d[b] = (d[a] - E[i].com)*E[i].rate;
			}
		}
		if(!update) break;
	}
	return false;
}


int main()
{
	int n, m, s;
	double v;
	while(scanf("%d%d%d%lf", &n, &m, &s, &v) == 4)
	{
		int a, b;
		double ra, co;
		for(int i=0; i<m; ++i)
		{
			scanf("%d%d", &a, &b);
			scanf("%lf%lf", &ra, &co); 
			E[i] = (edge){a, b, ra, co};
			scanf("%lf%lf", &ra, &co); 
			E[i+m] = (edge){b, a, ra, co};
		}
		numE = n*2;
		if(Bellman_Ford(s, v)) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值