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



  • 相关阅读:
    如何解除任务管理器被禁用
    一、JavaScript概述
    001_html基本结构
    postman常见问题记录
    fidder工具使用
    SonarQube工具使用问题汇总
    业余书籍读后感
    jmater常见问题处理
    测试知识记录(更新中)
    HTTP协议
  • 原文地址:https://www.cnblogs.com/agenthtb/p/6348079.html
Copyright © 2011-2022 走看看