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了。



  • 相关阅读:
    项目管理沙龙第十一次聚会纪要当敏捷没有共识的时候
    项目管理沙龙第十次聚会纪要AOM项目的敏捷实践
    项目管理沙龙第五次聚会
    微信小程序引入Vant组件
    Es6 Promise 及 截图软件Snipaste.exe
    微信小程序封装Request功能,请求接口
    我画的第二个 微信小程序页面
    我画的第一个 微信小程序页面
    微信小程序Vant获取用户信息及手机号
    小程序接入Echarts组件库
  • 原文地址:https://www.cnblogs.com/agenthtb/p/6348079.html
Copyright © 2011-2022 走看看