POJ 1860
题目大意:
有个城市有m种货币,n个货币兑换站。每两种货币兑换分别有相应的汇率和手续费。
例如,你现在有s个A货币,那么用A货币兑换B货币,你可得到(s-cab(A兑换B的手续费))*Rab(A兑换B的汇率)个B货币。
你现在有第S种货币V个,然后问你,是否能通过一系列的兑换,使得最后自己手中的第S种增加了。。。
大致思路:
此题要用最短路的思想进行求解,dis[i]代表当我兑换了第i种货币时,能兑换的数量。那么要使得原来的货币数量增加,那肯定是通过一系列的兑换之后,使得dis[start]>dis[start](开始的,即V)。
既然能回来,那说明一定会有环。既然有环,我们就要使用Bellman-Ford算法或者spfa。这两种都是可以进行存在环的的寻求最短路算法。我选用的是spfa算法,当存在dis[start]>V时就说明成功了。
此题和原来的最短路思想恰好相反,我们要把dis数组初始化为0。然后当兑换的货币数量大于原来的,就进行松弛。
代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
double dis[105];
int vis[105];
int m,n,s;
double v;
struct Node
{
int to;
double rat,cos;
Node(int too,double ratt,double coss)
{
to=too;
rat=ratt;
cos=coss;
}
};
vector<Node>V[105];//用vector存图
void init()
{
for(int i=1; i<=105; i++)
V[i].clear();
int a,b;
double rab,cab,rba,cba;
for(int i=0; i<n; i++)
{
scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba);
V[a].push_back(Node(b,rab,cab));
V[b].push_back(Node(a,rba,cba));
}
return;
}
int spfa()//我们要的是spfa的这种思想,这题并不是求最短路。。
{
queue<int>Q;
while(!Q.empty())Q.pop();
for(int i=0; i<=105; i++)
{
dis[i]=0;//初始化成0.当兑换第i种货币时,若大于原来的,就进行松弛。
vis[i]=0;
}
dis[s]=v;
Q.push(s);
vis[s]=1;
while(!Q.empty())
{
int top=Q.front();
Q.pop();
vis[top]=0;
for(int i=0;i<V[top].size();i++)
{
if(dis[V[top][i].to]<(dis[top]-V[top][i].cos)*V[top][i].rat)
{
dis[V[top][i].to]=(dis[top]-V[top][i].cos)*V[top][i].rat;//cout<<"++"<<dis[V[top][i].to]<<endl;
if(!vis[V[top][i].to])
{
Q.push(V[top][i].to);
vis[V[top][i].to]=1;
}
}
if(dis[s]>v)//增值了,成功了
return 1;
}
}
return 0;
}
int main()
{
scanf("%d%d%d%lf",&m,&n,&s,&v);
init();
if(spfa())
printf("YES\n");
else
printf("NO\n");
}