zoukankan      html  css  js  c++  java
  • 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了。



  • 相关阅读:
    在Ubuntu18.04.2LTS上安装搜狗输入法
    生活点滴:java基础知识细化
    乘风破浪:LeetCode真题_041_First Missing Positive
    乘风破浪:LeetCode真题_040_Combination Sum II
    乘风破浪:LeetCode真题_039_Combination Sum
    乘风破浪:LeetCode真题_038_Count and Say
    乘风破浪:LeetCode真题_037_Sudoku Solver
    乘风破浪:LeetCode真题_036_Valid Sudoku
    乘风破浪:LeetCode真题_035_Search Insert Position
    乘风破浪:LeetCode真题_034_Find First and Last Position of Element in Sorted Array
  • 原文地址:https://www.cnblogs.com/agenthtb/p/6348079.html
Copyright © 2011-2022 走看看