题目大意: 有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;
}