POJ 2240 - Arbitrage(最短路)

题意:

给出一些货币和货币之间的兑换比率,问是否可以使某种货币经过一些列兑换之后,货币值增加。

举例说就是1美元经过一些兑换之后,超过1美元。可以输出Yes,否则输出No。

分析:

首先我们要把货币之间的关系转化成一张图。转化时,用STL里面的map很方便。

为每种货币分配一个序列号,一个序列号代表了一个图中间的NODE,而node之间的edge用汇率表示。

一开始用Dijkstra算法做,死活AC不了,网友给的理由是:

由于Dijkstra算法不能处理带有负权值的最短路,但此题中,两种货币之间的兑换比率可能小于1,相当于这条路径的权值为负

前车之鉴,WA的代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<string.h>
 5 #include<string>
 6 #include<map>
 7 using namespace std;
 8 #define maxn 31
 9 #define inf 0x3f3f3f3f
10 double edges[maxn][maxn];
11 double dist[maxn];
12 typedef pair<int,int> P;
13 void init(){
14     for(int i=1;i<maxn;i++)
15         for(int j=1;j<maxn;j++)
16             edges[i][j]=(i==j?1:0);//1代表等价价换,0:代表无法交换
17 }
18
19 void dijkstra(int s,int n){
20     bool visited[maxn];
21     memset(visited,0,sizeof(visited));
22     visited[s]=true;
23     for(int i=1;i<=n;i++)
24         dist[i]=edges[s][i];
25     for(int i=1,u;i<=n;i++){
26         double max=-1;
27         for(int j=1;j<=n;j++)
28             if(!visited[j]&&dist[j]>max){
29                 max=dist[j]; u=j;
30             }
31
32         visited[u]=true;
33         for(int j=1;j<=n;j++){
34             if(dist[u]*edges[u][j]>dist[j])
35                 dist[j]=dist[u]*edges[u][j];
36         }
37     }
38 }
39
40 int main(){
41     //freopen("in.txt","r",stdin);
42     int n,cases=0;
43     while(scanf("%d",&n)!=EOF && n){
44         cases++;
45         init();
46         map<string,int> ma;
47         string s,t;
48         for(int i=1;i<=n;i++){
49             cin>>s;
50             ma.insert(make_pair(s,i));
51         }
52         int m;
53         double tmp;
54         scanf("%d",&m);
55         while(m--){
56             cin>>s>>tmp>>t;
57             edges[ma[s]][ma[t]]=tmp;
58         }
59
60         dijkstra(1,n);
61         printf("Case %d: ",cases);
62         if(dist[1]>1.0)
63             printf("Yes\n");
64         else
65             printf("No\n");
66     }
67 }

最后写了一个Floyd的代码版本,结果一下子就过了,我只能默默的哭了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<string.h>
 5 #include<string>
 6 #include<map>
 7 using namespace std;
 8 #define maxn 31
 9 #define inf 0x3f3f3f3f
10 double edges[maxn][maxn];
11 void init(){
12     for(int i=1;i<maxn;i++)
13         for(int j=1;j<maxn;j++)
14             edges[i][j]=(i==j?1:0);//1:代表等价交换,0:代表无法交换
15 }
16
17 void floyd_warshall(int s,int n){
18     for(int k=1;k<=n;k++){
19         for(int i=1,u;i<=n;i++){
20             for(int j=1;j<=n;j++){
21                 if(edges[i][k]*edges[k][j]>edges[i][j])//如果找到了更好的交换方案
22                     edges[i][j]=edges[i][k]*edges[k][j];
23             }
24         }
25     }
26 }
27
28 int main(){
29     //freopen("in.txt","r",stdin);
30     int n,cases=0;
31     while(scanf("%d",&n)!=EOF && n){
32         cases++;
33         init();
34         map<string,int> ma;
35         string s,t;
36         for(int i=1;i<=n;i++){
37             cin>>s;
38             ma.insert(make_pair(s,i));
39         }
40         int m;
41         double tmp;
42         scanf("%d",&m);
43         while(m--){
44             cin>>s>>tmp>>t;
45             edges[ma[s]][ma[t]]=tmp;
46         }
47
48         dijkstra(1,n);
49         printf("Case %d: ",cases);
50         /*for(int i=1,u;i<=n;i++){
51             for(int j=1;j<=n;j++){
52                 printf("%.2f  ",edges[i][j]);
53             }
54             printf("\n");
55         }*/
56         if(edges[1][1]>1.0)
57             printf("Yes\n");
58         else
59             printf("No\n");
60     }
61 }

【问题】:Folyd算法能处理包含负权边的图吗?

答案是可以的。Floyd-Warshall算法和Bellman-Ford算法一样,可以处理边是负数的情况。

---《挑战程序设计竞赛》 P.103

时间: 2025-01-17 18:27:50

POJ 2240 - Arbitrage(最短路)的相关文章

POJ 2240 Arbitrage(最短路 套汇)

题意  给你n种币种之间的汇率关系  判断能否形成套汇现象  即某币种多次换为其它币种再换回来结果比原来多 基础的最短路  只是加号换为了乘号 #include<cstdio> #include<cstring> #include<string> #include<map> using namespace std; map<string, int> na; const int N = 31; double d[N], rate[N][N], r;

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

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 就无法得到最优的,环

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 (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

[ 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-ford 判断正环)

http://poj.org/problem?id=2240 基本和poj 1860相同 只是把单点变成了任意点 做完1860再做这题就完全把思路套上就过了 做完才发现网上的题解都用的是floyd 不过整体思路都是大同小异吧 不过在效率上好像就低下了太多= = #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<stack> #include<

poj 2240 Arbitrage(Bellman-Ford算法学习)

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

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 Frenc