题意:有N种货币类型,两种货币之间可以相互兑换。例如:价值V的货币A兑换货币B,需要扣除兑换税Cab,然后乘兑换率Rab才能得到兑换后的货币B,V'=(V-Cab)*Rab。一共有M个兑换点,每个兑换点都只可以兑换两种货币(每个兑换点的数据为A,B,Cab,Rab,Cba,Rba)。当拥有价值为V的S货币时,是否通过兑换能够得到价值大于V的S货币。
要求:1<=S<=N<=100, 1<=M<=100, V is real number, 0<=V<=10^3
想法:其实一开始并没有什么想法,后来就学习了一个Bellman-Ford算法,但是一直也没看明白。。。效率之低。。嗯。。后来就明白了。。。具体内容在代码里。。。贴代码。。
代码如下:
<pre class="html" name="code">#pragma warning(disable:4996)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<stack>
#include<cstring>
#include<sstream>
#include<set>
#include<string>
#include<iterator>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
struct W {
int i, j;
double r, c;
}edge[260];
int main(void) {
int n, m, s, a, b;
double v, r1, r2, c1, c2;
//处理输入
cin >> n >> m >> s >> v;
for (int i = 0; i < m; ++i) {
cin >> a >> b >> r1 >> c1 >> r2 >> c2;
edge[i * 2].i = a;
edge[i * 2].j = b;
edge[i * 2].r = r1;
edge[i * 2].c = c1;
edge[i * 2 + 1].i = b;
edge[i * 2 + 1].j = a;
edge[i * 2 + 1].r = r2;
edge[i * 2 + 1].c = c2;
}
//建立权重数组
double *dis=new double[n];
memset(dis, 0, sizeof(double)*n);
dis[s - 1] = v;
//开始寻找最小路径
int uu, vv;
bool flag = 1;//判断是否还能再继续松弛
for (int i = 0; i < n&&flag; ++i){//进行n-1次松弛操作,得到最小路径
flag = 0;//如果这次松弛操作不能再继续松弛,那么得到最小路径
for (int j = 0; j < 2 * m; ++j) {
uu = edge[j].j - 1, vv = edge[j].i - 1;
if (dis[uu] < (dis[vv] - edge[j].c)*edge[j].r) {
dis[uu] = (dis[vv] - edge[j].c)*edge[j].r;
flag = 1;//这一次的松弛操作还可以松弛
}
}
}
if (flag)cout << "YES" << endl;//flag=1,说明即使做了n-1次松弛操作,路径还能继续松弛,说明还有正循环
else cout << "NO" << endl;
return 0;
}