【POJ 1860】Currency Exchange(Bellman_Ford)

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 R AB, C AB, R BA and C BA – 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<=10 3.
For each point exchange rates and commissions are real, given with at most two digits after the decimal point, 10 -2<=rate<=10 2, 0<=commission<=10 2.
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 10 4.

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,S,V分别表示这个城市的货币种类数量,M表示可以转换货币的方式数量,S表示你所持有的货币类型,V表示你所持货币的价值。接下来M行每行有6个数a,b,Rab,Cab,Rba,Cba,分别表示a,b货币之间的兑换,Rab表示从a货币兑换到b货币的汇率,Cab为手续费,同理后面两个参数。

思路

这题其实不是最短路问题,但是很多人将这题归到最短路中,其实这题只是用了bellman-Ford这个算法来巧妙地解决这一题,我们知道Bellman_Ford算法用于判断图中是否存在负权边,回归到这题,经过一系列兑换后要使自己所持货币的价值上升,那么可以想象我如果找到了这样一条兑换路径,那么我一直重复沿着这条兑换路径兑换下去我的钱是不是会变的越来越多。讲到这里应该很多人应该知道具体的思路了,就是使用Bellman_Ford去判断是否存在一条正权边可以无限松弛,如果存在则表示存在这样一条转换路径。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn=100+5;

struct proc
{
    int s,e;
    double r,c;
}cur[maxn*2];

double dis[maxn],c;
int n,m,s;
int cnt;

void addEdge(int s,int e,double r,double c)
{
    cur[cnt].s=s;
    cur[cnt].e=e;
    cur[cnt].r=r;
    cur[cnt++].c=c;
}


bool bellman()
{
    memset(dis,0,sizeof(dis));
    dis[s]=c;
    bool flag;
    //松弛操作
    for(int i=1;i<=n-1;i++)
    {
        flag=false;
        for(int j=0;j<cnt;j++)
        {
            if(dis[cur[j].e]<(dis[cur[j].s]-cur[j].c)*cur[j].r)
            {
                dis[cur[j].e]=(dis[cur[j].s]-cur[j].c)*cur[j].r;
                flag=true;
            }
        }
        if(!flag) break;
    }
    //寻找可以无限松弛的正权边
    for(int j=0;j<cnt;j++)
    {
        if(dis[cur[j].e]<(dis[cur[j].s]-cur[j].c)*cur[j].r)
            return true;
    }
    return false;
}

int main()
{
    while(~scanf("%d %d %d %lf",&n,&m,&s,&c))
    {
        cnt=0;
        for(int i=1;i<=m;i++)
        {
            int a,b;
            double r1,c1,r2,c2;
            scanf("%d %d %lf %lf %lf %lf",&a,&b,&r1,&c1,&r2,&c2);
            addEdge(a,b,r1,c1);
            addEdge(b,a,r2,c2);
        }
        if(bellman())
        {
            printf("YES\n");
        }
        else 
        {
            printf("NO\n");
        }
    }
    return 0;
}
    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/iceiceicpc/article/details/52241116
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞