题目大意:有n种货币,m个交换站,每个交换站表示可以兑换两种货币,并给出相互的汇率和手续费。给出初始货币种类和数量,问是否能赚钱。
因为边都是双向的,如果从起点搜出正环,则一定能无限走这个正环然后换回起点赚钱。那么SPFA判正环即可。
#include<cstdio> #include<iostream> #include<queue> using namespace std; #define pii pair<int,int> #define v first #define w second #define ll long long #define pb push_back #define rep(i,n) for(int i=1;i<=n;i++) struct edge{ int to; double com,rate; edge(int _to,double _com,double _rate):to(_to),com(_com),rate(_rate){}; }; const int N=120; const int inf=-(1<<30); vector<edge> e[N]; int n,m,s,vis[N],cnt[N]; double v,dist[N]; bool spfa(int s,int n){ rep(i,n)dist[i]=inf; vis[s]=1; dist[s]=v; queue<int> q; q.push(s); cnt[s]=1; while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; for(int i=0;i<e[u].size();i++){ int v=e[u][i].to; if(e[u][i].rate*(dist[u]-e[u][i].com)>dist[v]){ dist[v]=e[u][i].rate*(dist[u]-e[u][i].com); if(!vis[v]){ vis[v]=1; q.push(v); if(++cnt[v]>n)return 0; } } } } return 1; } int main(){ ios::sync_with_stdio(false); cin>>n>>m>>s>>v; rep(i,m){ int u,v; double r1,c1,r2,c2; cin>>u>>v>>r1>>c1>>r2>>c2; e[u].pb(edge(v,c1,r1)); e[v].pb(edge(u,c2,r2)); } if(!spfa(s,n)){ cout<<"YES"; } else cout<<"NO"; }