zoukankan      html  css  js  c++  java
  • POJ2240:Arbitrage(最长路+正环)

    Arbitrage

    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 29374   Accepted: 12279

    题目链接:http://poj.org/problem?id=2240

    Description:

    Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of a currency into more than one unit of the same currency. For example, suppose that 1 US Dollar buys 0.5 British pound, 1 British pound buys 10.0 French francs, and 1 French franc buys 0.21 US dollar. Then, by converting currencies, a clever trader can start with 1 US dollar and buy 0.5 * 10.0 * 0.21 = 1.05 US dollars, making a profit of 5 percent. 

    Your job is to write a program that takes a list of currency exchange rates as input and then determines whether arbitrage is possible or not. 

    Input:

    The input will contain one or more test cases. Om the first line of each test case there is an integer n (1<=n<=30), representing the number of different currencies. The next n lines each contain the name of one currency. Within a name no spaces will appear. The next line contains one integer m, representing the length of the table to follow. The last m lines each contain the name ci of a source currency, a real number rij which represents the exchange rate from ci to cj and a name cj of the destination currency. Exchanges which do not appear in the table are impossible. 
    Test cases are separated from each other by a blank line. Input is terminated by a value of zero (0) for n.

    Output:

    For each test case, print one line telling whether arbitrage is possible or not in the format "Case case: Yes" respectively "Case case: No".

    Sample Input:

    3
    USDollar
    BritishPound
    FrenchFranc
    3
    USDollar 0.5 BritishPound
    BritishPound 10.0 FrenchFranc
    FrenchFranc 0.21 USDollar
    
    3
    USDollar
    BritishPound
    FrenchFranc
    6
    USDollar 0.5 BritishPound
    USDollar 4.9 FrenchFranc
    BritishPound 10.0 FrenchFranc
    BritishPound 1.99 USDollar
    FrenchFranc 0.09 BritishPound
    FrenchFranc 0.19 USDollar
    
    0

    Sample Output:

    Case 1: Yes
    Case 2: No

    题意:

    给出几种货币单位,以及货币与货币之间的兑换汇率,问最后是否能够套利。就是用1个单位的货币,不断去兑换其它的货币,最后得到大于1个单位的相应货币。

    题解:

    总的思路就是跑最长路看看是否有正环吧,有的话就说明至少存在一种货币可以用来套利。

    这里跑最长路的时候要把之前的“ + ”改造为“ * ”,至于正确性,乘法取个对数也等价于加吧?具体证明我也不是很清楚。

    代码如下:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <cmath>
    #include <map>
    #include <string>
    #include <stack>
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int N = 35;
    map <string ,int> mp;
    int n,num;
    struct Edge{
        int u,v,next;
        double w;
    }e[N*N<<1];
    int head[N],vis[N],c[N];
    int tot;
    void adde(int u,int v,double w){
        e[tot].v=v;e[tot].w=w;e[tot].next=head[u];head[u]=tot++;
    }
    double d[N];
    int spfa(int s){
        memset(d,0,sizeof(d));memset(vis,0,sizeof(vis));
        d[s]=1;queue <int> q;q.push(s);memset(c,0,sizeof(c));
        c[s]=1;vis[s]=1;
        while(!q.empty()){
            int u=q.front();q.pop();vis[u]=0;
            for(int i=head[u];i!=-1;i=e[i].next){
                int v=e[i].v;
                if(d[v]<d[u]*e[i].w){
                    d[v]=d[u]*e[i].w;
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                        if(++c[v]>n) return 1;
                    }
                }
            }
        }
        return 0;
    }
    int main(){
        int cnt =0;
        while(scanf("%d",&n)!=EOF){
            if(n==0) break ;
            string s;
            num=0;cnt++;
            for(int i=1;i<=n;i++){
                cin>>s;
                mp[s]=++num;
            }
            int tmp;
            scanf("%d",&tmp);
            memset(head,-1,sizeof(head));tot=0;
            for(int i=1;i<=tmp;i++){
                string s1,s2;
                double w;
                cin>>s1>>w>>s2;
                adde(mp[s1],mp[s2],w);
            }
            printf("Case %d: ",cnt);
            if(spfa(1)) puts("Yes");
            else puts("No");
        }
        return 0;
    }
  • 相关阅读:
    hiho 1483 区间计数问题+二分答案
    Educational Codeforces Round 17 D dp
    Educational Codeforces Round 17 C 二分
    hiho 1461 暴力+随机
    (转)重置Mac OS X管理员密码
    解析Xcode把应用程序打包成ipa---解决打包完新版本itunes提示不是有效应用程序的问题
    SVN权限修复
    MAC安装SVNServer
    设置UIScrollView只可以水平或者竖直滚动
    (转)android之Fragment(官网资料翻译)
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10352067.html
Copyright © 2011-2022 走看看