题意是两种货币可以互相兑换,交换的时候需要交手续费。
e.g 当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。
求经过不定次数兑换回原来的钱能否增加。
大神的分析:
一种货币就是图上的一个点。
一个“兑换点”就是图上两种货币之间的一个兑换环,相当于“兑换方式”M的个数,是双边。
唯一值得注意的是权值,当拥有货币A的数量为V时,A到A的权值为K,即没有兑换。
而A到B的权值为(V-Cab)*Rab。
本题是“求最大路径”,之所以被归类为“求最小路径”是因为本题题恰恰与bellman-Ford算法的松弛条件相反,求的是能无限松弛的最大正权路径,但是依然能够利用bellman-Ford的思想去解题。
因此初始化d(S)=V 而源点到其他店的距离(权值)初始化为无穷小(0),当s到其他某点的距离能不断变大时,说明存在最大路径。
代码:
#include<stdio.h>
int n;//货币种数
int m;//兑换点数
int s;//持有第s种货币
double v;//s种货币的本金
int l;//总边数
double dis[101];//s到各点权值
struct exchange
{
int a;//货币a
int b;//货币b
double r;//税率
double c;//手续费
}e[202];
bool bellman()
{
for(int i = 0; i < m; i++)
dis[i] = 0;
dis[s] = v;
for(int i = 1; i <= n-1; i++)
{
bool over = true;
for(int j = 0; j < l; j++)
{
if(dis[e[j].b] < (dis[e[j].a] - e[j].c) * e[j].r)
{
dis[e[j].b] = (dis[e[j].a] - e[j].c) * e[j].r;
over = false;
}
}
if(over)
{
break;
}
}
for(int j = 0; j < l; j++)
{
if(dis[e[j].b] < (dis[e[j].a] - e[j].c) * e[j].r)
return true;
}
return false;
}
int main()
{
int ta, tb;
double rab, rba, cab, cba;
while(scanf("%d%d%d%lf", &n, &m, &s, &v)!=EOF)
{
l = 0;//0个边
for(int i = 0; i < m; i++)
{
scanf("%d%d%lf%lf%lf%lf", &ta, &tb, &rab, &cab, &rba, &cba);
e[l].a = ta;
e[l].b = tb;
e[l].r = rab;
e[l++].c = cab;
e[l].a = tb;
e[l].b = ta;
e[l].r = rba;
e[l++].c = cba;
}
if(bellman())
printf("YES\n");
else
printf("NO\n");
}
return 0;
}