思路:用spfa来找正环,只要存在一个正环(cnt >= n),那么走这个圈无穷次后资产一定正无穷,因为路是双向的,所以一定可以返回原来的货币,正无穷再怎么亏损,一定还是正无穷
AC Code
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int N = 2021;
int e[N], ne[N], h[N], idx;
double rate[N], cost[N]; //汇率 佣金
double money[N];
int n, m, s; //货币种类, 兑换地点, 当前钱种类
double v; // 当前钱数量
bool st[N];
int cnt[N];
void add(int a, int b, double r, double c)
{
e[idx] = b, rate[idx] = r, cost[idx] = c, ne[idx] = h[a]; h[a] = idx++;
}
bool spfa()
{
queue<int> q;
q.push(s);
st[s] = true;
cnt[s] = 0;
money[s] = v;
while(!q.empty())
{
int t = q.front();
q.pop();
st[t] = false;
for(int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
double tmp = (money[t] - cost[i]) * rate[i];
if(tmp > money[j])
{
money[j] = tmp;
cnt[j] = cnt[t] + 1;
if(cnt[j] >= n)
return true;
if(!st[j])
{
q.push(j);
st[j] = true;
}
}
}
}
return false;
}
int main()
{
cin >> n >> m >> s >> v;
memset(h, -1, sizeof h);
while(m--)
{
int a, b;
double r1, c1, r2, c2;
cin >> a >> b >> r1 >> c1 >> r2 >> c2;
add(a, b, r1, c1);
add(b, a, r2, c2);
}
cout << (spfa() ? "YES" : "NO") << endl;
return 0;
}