您的位置:首页 > 其它

poj1860 Currency Exchange(货币交换,最短路问题)

2013-12-13 00:16 381 查看
Currency Exchange

Time Limit: 1000MSMemory Limit: 30000K
Total Submissions: 17436Accepted: 6112
Description
Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and performs exchange operations only with these currencies. There can be several points specializing
in the same pair of currencies. Each point has its own exchange rates, exchange rate of A to B is the quantity of B you get for 1A. Also each exchange point has some commission, the sum you have to pay for your exchange operation. Commission is always collected
in source currency.

For example, if you want to exchange 100 US Dollars into Russian Rubles at the exchange point, where the exchange rate is 29.75, and the commission is 0.39 you will get (100 - 0.39) * 29.75 = 2963.3975RUR.

You surely know that there are N different currencies you can deal with in our city. Let us assign unique integer number from 1 to N to each currency. Then each exchange point can be described with 6 numbers: integer A and B - numbers of currencies it exchanges,
and real RAB, CAB, RBA and CBA - exchange rates and commissions when exchanging A to B and B to A respectively.

Nick has some money in currency S and wonders if he can somehow, after some exchange operations, increase his capital. Of course, he wants to have his money in currency S in the end. Help him to answer this difficult question. Nick must always have non-negative
sum of money while making his operations.

Input
The first line of the input contains four numbers: N - the number of currencies, M - the number of exchange points, S - the number of currency Nick has and V - the quantity of currency units he has. The following M lines contain
6 numbers each - the description of the corresponding exchange point - in specified above order. Numbers are separated by one or more spaces. 1<=S<=N<=100, 1<=M<=100, V is real number, 0<=V<=103.

For each point exchange rates and commissions are real, given with at most two digits after the decimal point, 10-2<=rate<=102, 0<=commission<=102.

Let us call some sequence of the exchange operations simple if no exchange point is used more than once in this sequence. You may assume that ratio of the numeric values of the sums at the end and at the beginning of any simple sequence of the exchange operations
will be less than 104.

Output
If Nick can increase his wealth, output YES, in other case output NO to the output file.
Sample Input
3 2 1 20.0
1 2 1.00 1.00 1.00 1.00
2 3 1.10 1.00 1.10 1.00

Sample Output
YES
题目大意:一土豪有n种货币,其中货币之间有m个兑换关系,每个兑换关系有6个数:u,v,r1,c1,r2,c2,分别表示从u货币兑换到v货币的汇率为r1,手续费为c1,从v货币交换到
u货币的汇率为r2,手续费为c2.土豪最初拥有s货币,价值为V。问:是否存在一种交换方式,使得土豪最后拥有s货币且大于最初的value。
具体的汇率和手续费,已题目中的例子为例if you want to exchange 100 US Dollars into Russian Rubles at the exchange point, where the exchange rate is 29.75, and the commission is 0.39 you will get (100 - 0.39) * 29.75 = 2963.3975RUR
假如该土豪有100块u货币,u转化到v的汇率为29.75,手续费为0.39,则得到的v货币为(100-0.39)*29.75=2963.3975

思路:根据,货币之间的转换关系建图,然后利用最长路算法(spfa或者bellmanFord)判断图中是否存在正环。
简单证明如下:



转化到本题中:由于是汇率 转化,因此最长路松弛操作变成了if(dist[v]<(dist[u]-r)*c  则dist[v]=(dist[u]-r)*c;
判断有无正环。。。spfa,或者bellmanFord就能轻松搞定了。。
ps:我艹,还是我太弱。。spfa的时候自己用int que[]来模拟数组,数组开得有点小,一直wa,后面stl了。。还是就用stl吧,方便又安全,基本情况下都是能满足的,没有那么慢啦
/*
@author : liuwen
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <cmath>
using namespace std;
const int maxn=105;
const int maxe=550;
const double inf=10000000.0;
struct NodeEdge{
int to,next;
double r,c;
}edges[maxe];
int head[maxn],n,m,s,nEdges;
double dist[maxn],value;
void addEdges(int u,int v,double r,double c)
{
nEdges++;
edges[nEdges].to=v;
edges[nEdges].r=r;
edges[nEdges].c=c;
edges[nEdges].next=head[u];
head[u]=nEdges;
}
bool spfa(int s)
{
bool vis[maxn];
int outque[maxn];
queue<int>que;  //一开用的是自己que[maxe*10]手工实现的队列。一直wa...数组开小了,才不能估计的情况下还是用stl吧,安全
memset(vis,0,sizeof(vis));
memset(outque,0,sizeof(outque));
for(int i=1;i<=n;i++)   dist[i]=-inf;
dist[s]=value;
vis[s]=true;
que.push(s);
while(!que.empty()){
int top=que.front();
que.pop();
vis[top]=false;
outque[top]++;
if(outque[top]>n)   return true; //如果出队次数超过n次,则存在正环,满足条件了
for(int k=head[top];k!=-1;k=edges[k].next){
int v=edges[k].to;
if(dist[v]<(dist[top]-edges[k].c)*edges[k].r){ //现在的松弛操作
dist[v]=(dist[top]-edges[k].c)*edges[k].r;
if(!vis[v]){
vis[v]=true;
que.push(v);
}
}
}
}
return false;
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d%d%d%lf",&n,&m,&s,&value)==4){
memset(head,-1,sizeof(head));
memset(edges,0,sizeof(edges));
nEdges=0;
for(int i=1;i<=m;i++){
int u,v;
double r1,c1,r2,c2;
cin>>u>>v>>r1>>c1>>r2>>c2;
addEdges(u,v,r1,c1);
addEdges(v,u,r2,c2);
}
if(spfa(s)){
printf("YES\n");
}else{
printf("NO\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: