poj_1860 Bellman-Ford算法的逆向应用

问题:货币兑换是否可以有增值

解法:

Bellman-Ford算法可以找出图G是否存在一个负权值回路,本题需要找出一个正权值回路,即经过一系列兑换后货币总额是增加的。

所谓正权回路就是从源点s出发的一条回路上,顶点的权值能不断增加,即边可以一直进行松弛操作。

建模:每一种货币是图G中的一个顶点,每一个兑换点是针对该兑换点的两种货币的兑换规则,即相当于两个顶点的两条边(正向和反向),本题即要求找出一条能无限松弛的最大正权路径。

初始化dist[s]=v,源点到其他点的权值为0,当s点到其它某点的距离能不断变大时,说明存在最大正权路径;

松弛条件:if(dist[exc[j].b] < (dist[exc[j].a] – exc[j].c)*exc[j].r)

即如果将当前货币a兑换成b后,比b处的值要大的话就进行兑换(松弛),经过(|N|-1)次每一条边的松弛后,每个顶点都是该种货币的最大兑换值,最后每条边再进行一次松弛,看是否能构成正权回路。

#include<iostream>  
#include<fstream>
#include<cstdio>  
using namespace std;

int N;//货币种类
int M;//兑换点数量
int S;//持有第S中货币
double V;//本金数量(S中货币)

int all_wedge;
double dist[101];

struct exchange_points{
	int a;
	int b;
	double r;
	double c;
}exc[202];

//存在正权回路,return TRUE
//不存在正权回路,return FALSE
bool Bellman_Ford()
{
	memset(dist, 0, sizeof(dist));
	dist[S] = V;
	for (int i = 1; i <= N - 1; i++)
	{
		for (int j = 0; j < all_wedge; j++)
		{
			if (dist[exc[j].b] < (dist[exc[j].a] - exc[j].c)*exc[j].r)
			{
				dist[exc[j].b] = (dist[exc[j].a] - exc[j].c)*exc[j].r;
			}
		}
	}
	for (int k = 0; k < all_wedge; k++)
	{
		if (dist[exc[k].b] < (dist[exc[k].a] - exc[k].c)*exc[k].r)
			return true;
	}
	return false;
}	

int main()
{
	int a, b;
	double rab, cab, rba, cba;
	//fstream in("text.txt");
	while (cin >> N >> M >> S >> V)
	{
		all_wedge = 0;
		for (int i = 0; i <= M; i++)
		{
			cin >> a >> b >> rab>> cab >> rba >> cba;
			exc[all_wedge].a = a;
			exc[all_wedge].b = b;
			exc[all_wedge].r = rab;
			exc[all_wedge++].c = cab;
			exc[all_wedge].a = b;
			exc[all_wedge].b = a;
			exc[all_wedge].r = rba;
			exc[all_wedge++].c = cba;
		}
		if (Bellman_Ford())
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	//system("pause");
	return 0;
}


    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/yeruby/article/details/38079589
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞