题意:给出n种货币,m个兑换点,每个兑换点给出两种货币之间的汇率及佣金,如A兑换为B可以兑换(A-佣金)*汇率的量。给出初始货币种类,以及持有货币量,求是否可以找到一种兑换方案,使得持有的初始种类货币量变多
思路:以初始货币为起始点,初始货币量为初始权值,初始点到其他点的路径权值设置为最小值(0),松弛操作判断是否可以使得当前点的金额变多,若松弛过程中遇到当前点为初始点,表明找到了正权环,初始货币量可以增加,存在答案;找不到正权环表明没有答案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 200+5;
const int inf = 0x3f3f3f3f;
int n, m, s, vis[maxn];
double V, dis[maxn];
struct node {
int v;
double rate, com;
node(int v = 0, double rate = 0, double com = 0) : v(v), rate(rate), com(com) {}
};
vector<node> g[maxn];
int main()
{
while (cin >> n) {
cin >> m >> s >> V;
for (int i = 0; i < m; i++) {
int u, v;
double r1, c1, r2, c2;
cin >> u >> v >> r1 >> c1 >> r2 >> c2;
g[u].push_back(node(v, r1, c1));
g[v].push_back(node(u, r2, c2));
}
memset(vis, 0, sizeof(vis));
memset(dis, 0, sizeof(dis));
dis[s] = V;
queue<int> q;
q.push(s);
int flag = 0;
while (!q.empty()) {
if (flag)
break;
int u = q.front(); q.pop();
vis[u] = 0;
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i].v;
double di = (dis[u]-g[u][i].com)*g[u][i].rate;
if (dis[v] < di) {
if (v == s) {
cout << "YES" << endl;
flag = 1;
break;
}
dis[v] = di;
if (!vis[v]) {
q.push(v);
vis[v] = 1;
}
}
}
}
if (!flag) {
cout << "NO" << endl;
}
}
return 0;
}