题意:
在一个城市中有 n 个货币交换点,每个交换点可以接受两种货币的交换,不同的交换方式有不同的汇率和手续费。问是否存在一种交换方式使得某人在这个交换过程中可以获利。
思路:
这道题不难,本题类似于负权环的检测,经过负权环之后,成本可以不断减少。如果我们在这道题中存在一个环可以使得我们不断获利,那么我们必然可以在整个过程中获利。我们在 Bellman-Ford 算法或者 SPFA 算法中对收入进行松弛。套用前面两个算法中的负权环检测方法即可求出。
代码:
#include <vector>
#include <iostream>
#include <cstdio>
#define N 105
#define fp(p,q,r) for(int p = q;p < r;p++)
typedef long long ll;
typedef double dl;
using namespace std;
ll n,m,s;
dl v,d[N];
struct edge{
ll from,to;
double rab,cab;
edge(ll a,ll b,dl c,dl d):from(a),to(b),rab(c),cab(d){};
};
vector <edge> edges;
bool bf(){
fill(d,d+N,0);
d[s]=v;
fp(i,0,n){
// bool f=0;
fp(j,0,2*m){
edge e=edges[j];
if(d[e.to]<(d[e.from]-e.cab)*e.rab){
d[e.to]=(d[e.from]-e.cab)*e.rab;
if(i==n-1) return true;//如果进行了 n - 1 次松弛,那么必存在“负权环”
// f=1;
}
}
// if(!f) break;
}
// fp(i,0,m*2){
// edge e=edges[i];
// if(d[e.to]<(d[e.from]-e.cab)*e.rab) return true;
// }
return false;
}
int main(void)
{
cin >> n >> m >> s >> v;
fp(i,0,2 * m){
ll a,b;dl c,d,e,f;
cin >> a >> b >> c >> d >> e >> f;
edges.push_back(edge(a,b,c,d));
edges.push_back(edge(b,a,e,f));
}
cout << (bf() ? "YES" : "NO") << endl;
return 0;
}