问题:货币兑换是否可以有增值
解法:
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;
}