题意:
有N个货币兑换所,每个兑换所兑换2种货币A和B。分别有汇率RAB,RBA,和回扣CAB,CBA;
问是否可以通过货币之间的转化而盈利。
思路:
一开始以为是dijk求单源点距离然后判断最后的距离是否大于初始值,后来发现做不出来。
看了discuss才发现用的是bellman_ford算法。好久没用了,都生疏了,就先去把以前的题看了一下,POJ3259。
只不过3259求的是是否存在负环,是bellman_ford的标准作法。
这题有点变形,求的是是否存在一个环使得两点之间的值可以无限递增。
只需要在最后判断环的步骤上改变一下即可
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <vector> #include <stack> #include <map> #include <iomanip> #define PI acos(-1.0) #define Max 2005 #define inf 1<<28 using namespace std; int n,m,s; double money; struct kdq { int u,v; double huilv; double cost; } currency[Max];//货币 double dis[Max]; void bellman_ford(int num) { int i,j; for(i=1; i<=n; i++) dis[i]=-inf;//因为求的是最大值,所以初始化的时候要dis[]--> -∞; dis[s]=money; bool flag=0; for(i=1; i<=n; i++) { for(j=1; j<=num; j++) { if(dis[currency[j].u]!=-inf&&dis[currency[j].v]<(dis[currency[j].u]-currency[j].cost)*currency[j].huilv)//松弛 { dis[currency[j].v]=(dis[currency[j].u]-currency[j].cost)*currency[j].huilv; } } } for(j=1; j<=num; j++)//判断是否形成无限增大的环 { double temp=(dis[currency[j].u]-currency[j].cost)*currency[j].huilv; if(dis[currency[j].v]!=-inf&&dis[currency[j].v]<temp)//如果dis[v]<temp,则证明该环可以无限增加,所以可以盈利 { flag=1; break; } } if(flag) cout<<"YES"<<endl; else cout<<"NO"<<endl; } int main() { int i,j,k,l,a,b; double Rab,Cab,Rba,Cba; cin>>n>>m>>s>>money; int num=0; for(i=1; i<=m; i++) { num++; cin>>a>>b>>Rab>>Cab>>Rba>>Cba; currency[i].u=a,currency[i].v=b; currency[i].huilv=Rab,currency[i].cost=Cab; num++; currency[i+m].u=b,currency[i+m].v=a; currency[i+m].huilv=Rba,currency[i+m].cost=Cba; } bellman_ford(2*m); return 0; }