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\n",++casee);
100         else
101             printf("Case %d: No\n",++casee);
102     }
103     return 0;
104 }

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

				
时间: 2024-12-12 16:02:09

POJ 2240 Arbitrage (spfa判环)的相关文章

poj2240 Arbitrage (spfa判环)

Arbitrage Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10997   Accepted: 4622 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 currenc

[ An Ac a Day ^_^ ][kuangbin带你飞]专题四 最短路练习 POJ 2240 Arbitrage spfa求负环

题意就是问倒腾外币能不能升值 不用spfa 用其他的最短路算法也可以 松弛条件换成dist[v]<dist[u]*e[u][i].value 当然 貌似只有spfa有这个坑…… 有A  (value>1.0) A 这种情况……我的天 用Dij Floyd都只用判断如果松弛到了自己 那么一定有环 直接跳出就行 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<

POJ 2240 Arbitrage

Bellman 求最大环. 询问货币是否纯在套汇. 假如给你 1 元,通过兑换之后 超过 1 元就是存在套汇了. 用 map 映射比较方便. #include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<queue> #include<map> #include<iostream>

POJ 2240 -- Arbitrage(Bellman-Ford)

POJ 2240 -- Arbitrage(Bellman-Ford) 题意: 已知n种货币,以及m种货币汇率及方式,问能否通过货币转换,使得财富增加. Bellman-ford 算法: 一个具有n个顶点的图如果不存在环,则从顶点x,到顶点y,最多经过n-1条边(要考虑连通性,每个顶点最多经过 1 次),因此 x 到 y 的最短路 最多经过 n - 1 次松弛操作(就是更新长度)就应该出现,如果第 n 次松弛还可以得到最优,那么这个图就肯定是存在环了(直接用Dijkstra 就无法得到最优的,环

hdu 1317 XYZZY(spfa判环)

http://acm.hdu.edu.cn/showproblem.php?pid=1317 大致题意:有n个房间,每个房间都有对应的能量值(可正可负),现在从1出发要到达n,初始能量为100,问是否能够达到n点,到达n的条件是中间及最后的能量值都要大于0. 思路:若不考虑环,那么求最长路判断是否大于0即可.若存在负环,对求最长路也没影响:但当存在正环时,最长路就不存在了.可用spfa判断,当某点入队超过n次,那么它必定在环中,直接将其dis置为INF,并不再将其近队列.最后若能到达n则可行,否

poj 2240 Arbitrage 题解

Arbitrage Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 21300   Accepted: 9079 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 currenc

【BZOJ 3232】圈地游戏 二分+SPFA判环/最小割经典模型

最小割经典模型指的是“一堆元素进行选取,对于某个元素的取舍有代价或价值,对于某些对元素,选取后会有额外代价或价值”的经典最小割模型,建立倒三角进行最小割.这个二分是显然的,一开始我也是想到了最小割的那个模型的但是我觉得他会不是一个圈我就否掉了,但是仔细想想的话会发现,如果是这样的话所得到的答案一定小于等于一个圈的答案(浓度),所以我们可定会得到最终答案,所以这样做是可以的,所以说要有宽松得正解的意识(泥沙俱下但沙子不影响我泥).当时我否掉最小割以后就立马去想费用流了,然后想到建图后发现那样建图虽

POJ 3259 Wormholes(SPFA判负环)

题目链接:http://poj.org/problem?id=3259 题目大意是给你n个点,m条双向边,w条负权单向边.问你是否有负环(虫洞). 这个就是spfa判负环的模版题,中间的cnt数组就是记录这个点松弛进队的次数,次数超过点的个数的话,就说明存在负环使其不断松弛. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using na

poj 2240 Arbitrage (Floyd)

链接:poj 2240 题意:首先给出N中货币,然后给出了这N种货币之间的兑换的兑换率. 如 USDollar 0.5 BritishPound 表示 :1 USDollar兑换成0.5 BritishPound. 问在这N种货币中是否存在货币经过若干次兑换后,兑换成原来的货币能够使货币量添加. 思路:本题事实上是Floyd的变形.将变换率作为构成图的路径的权值.只是构成的图是一个有向图. 最后将松弛操作变换为:if(dis[i][j]<dis[i][k]*dis[k][j]). #includ