• POJ 2240 Arbitrage (spfa判环)


    Arbitrage
    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

    给你一个汇率表,找出其中有没有一种能创造无限金钱的环?这是我第一次写的比较清醒的spfa。
    spfa判环有两种:
    1.dfs:判断某个点是否在同一条路径出现多次
    2.bfs:判断某个点入队的次数是否大于自身的入度
    代码如下:
      1 #include <iostream>
      2 #include <queue>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <map>
      8 #include <vector>
      9 using namespace std;
     10 #define M 9000
     11 map <string,int> money;//将货币映射成数字
     12 struct Edge
     13 {
     14     int u,v;
     15     double rate;
     16 }edge[M];
     17 vector <int> g[50];//存图
     18 bool inque[50];//标记是否入队
     19 double price[50];//到达某点的最大汇率(类似距离)
     20 int cnt[50];//标记点的入队次数
     21 int in_degree[50];//入度
     22 int toNum (string x)
     23 {
     24     return money[x];
     25 }
     26 int n,m;
     27 void init()
     28 {
     29     for (int i=0;i<50;++i){
     30         inque[i]=false;
     31         price[i]=0;
     32         cnt[i]=0;
     33     }
     34 }
     35 bool spfa(int x)
     36 {
     37     queue<int>q;
     38     cnt[x]++;
     39     price[x]=1.0;
     40     inque[x]=true;
     41     q.push(x);
     42     while (!q.empty()){
     43         int now=q.front();
     44         q.pop();
     45         inque[now]=false;
     46         for (int i=0;i<g[now].size();++i){
     47             int e=g[now][i];
     48             int nxt=edge[e].v;
     49             if (price[nxt]<price[now]*edge[e].rate){
     50                 price[nxt]=price[now]*edge[e].rate;//松弛
     51                 if (!inque[nxt]){
     52                     inque[nxt]=true;
     53                     q.push(nxt);
     54                     if (++cnt[nxt]>in_degree[nxt]){//某点的入队次数大于它的入度
     55                         return true;
     56                     }
     57                 }
     58             }
     59         }
     60     }
     61     return false;
     62 }
     63 int main()
     64 {
     65     //freopen("de.txt","r",stdin);
     66     int casee=0;
     67     while (~scanf("%d",&n)){
     68         if (n==0) break;
     69         money.clear();
     70         for(int i=0;i<50;++i)
     71             g[i].clear();
     72         for (int i=0;i<50;++i)
     73             in_degree[i]=0;
     74         for (int i=0;i<n;++i){
     75             string mny;
     76             cin>>mny;
     77             money[mny]=i;
     78         }
     79         scanf("%d",&m);
     80         for (int i=0;i<m;++i){
     81             string a,b;
     82             double x;
     83             cin>>a>>x>>b;
     84             edge[i].u=toNum(a);
     85             edge[i].v=toNum(b);
     86             edge[i].rate=x;
     87             g[edge[i].u].push_back(i);
     88             in_degree[edge[i].v]++;
     89         }
     90         bool ok=false;
     91         for (int i=0;i<n;++i){//从每个点跑spfa
     92             init();//记得每次初始化
     93             if (spfa(i)){
     94                 ok=true;
     95                 break;
     96             }
     97         }
     98         if (ok)
     99             printf("Case %d: Yes
    ",++casee);
    100         else
    101             printf("Case %d: No
    ",++casee);
    102     }
    103     return 0;
    104 }

    这题813ms过的...folyd好像只要几十ms,就当练习spfa了。



  • 相关阅读:
    shell中exec解析
    linux expr命令参数及用法详解
    Linux中变量#,#,@,0,0,1,2,2,*,$$,$?的含义
    Q_DISABLE_COPY
    lower_bound()函数
    滚动数组
    POJ 1159 Palindrome(LCS)
    C语言中short的意思
    ZOJ 2432 Greatest Common Increasing Subsequence(最长公共上升子序列+路径打印)
    ZOJ 1004 Anagrams by Stack(DFS+数据结构)
  • 原文地址:https://www.cnblogs.com/agenthtb/p/6348079.html
Copyright © 2020-2023  润新知