POJ2240:Arbitrage(最长路+正环)

Arbitrage

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 29374   Accepted: 12279

题目链接:http://poj.org/problem?id=2240

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

题意:

给出几种货币单位,以及货币与货币之间的兑换汇率,问最后是否能够套利。就是用1个单位的货币,不断去兑换其它的货币,最后得到大于1个单位的相应货币。

题解:

总的思路就是跑最长路看看是否有正环吧,有的话就说明至少存在一种货币可以用来套利。

这里跑最长路的时候要把之前的“ + ”改造为“ * ”,至于正确性,乘法取个对数也等价于加吧?具体证明我也不是很清楚。

代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <string>
#include <stack>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 35;
map <string ,int> mp;
int n,num;
struct Edge{
    int u,v,next;
    double w;
}e[N*N<<1];
int head[N],vis[N],c[N];
int tot;
void adde(int u,int v,double w){
    e[tot].v=v;e[tot].w=w;e[tot].next=head[u];head[u]=tot++;
}
double d[N];
int spfa(int s){
    memset(d,0,sizeof(d));memset(vis,0,sizeof(vis));
    d[s]=1;queue <int> q;q.push(s);memset(c,0,sizeof(c));
    c[s]=1;vis[s]=1;
    while(!q.empty()){
        int u=q.front();q.pop();vis[u]=0;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(d[v]<d[u]*e[i].w){
                d[v]=d[u]*e[i].w;
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                    if(++c[v]>n) return 1;
                }
            }
        }
    }
    return 0;
}
int main(){
    int cnt =0;
    while(scanf("%d",&n)!=EOF){
        if(n==0) break ;
        string s;
        num=0;cnt++;
        for(int i=1;i<=n;i++){
            cin>>s;
            mp[s]=++num;
        }
        int tmp;
        scanf("%d",&tmp);
        memset(head,-1,sizeof(head));tot=0;
        for(int i=1;i<=tmp;i++){
            string s1,s2;
            double w;
            cin>>s1>>w>>s2;
            adde(mp[s1],mp[s2],w);
        }
        printf("Case %d: ",cnt);
        if(spfa(1)) puts("Yes");
        else puts("No");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/heyuhhh/p/10352067.html

时间: 2024-12-18 22:02:20

POJ2240:Arbitrage(最长路+正环)的相关文章

NYOJ 973 天下第一(最长路判环)

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=973 题目大意:给你n种武功,每两种武功都可以相互转化,但是有转化率f, 每次必须从一开始转化, 中间有武功转化不了, 后面的就不能在转化了, 问你能否可以无限增加转化. 在做这道题以前做了和这道题一样的一道题, 所以我认为很快就能AC了, 但是这道题我还是弄了一天还是没能AC.来讲一下让我很是郁闷的问题吧. 这道题可以用最短路判环(spfa只需稍微变一下)来做,也可以用直接深搜来做.我

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<

hdu 1317 SPFA+连通判断+最长路

Description It has recently been discovered how to run open-source software on the Y-Crate gaming device. A number of enterprising designers have developed Advent-style games for deployment on the Y-Crate. Your job is to test a number of these design

HDU 3249 Test for job (有向无环图上的最长路,DP)

 解题思路: 求有向无环图上的最长路,简单的动态规划 #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include <cmath> #define LL long long using namespace std; const int

POJ 2240 Arbitrage Bellman_ford 判读是否存在正环

和POJ1860差不多,就是用bellmanford判读是否存在正环,注意的是同种货币之间也可以交换,就是说:A货币换A货币汇率是2的情况也是存在的. #include<stdio.h> #include<string.h> #include<cstring> #include<string> #include<math.h> #include<queue> #include<algorithm> #include<

【连通图|强连通分量+最长路】POJ-3592 Instantaneous Transference

Instantaneous Transference Time Limit: 5000MS Memory Limit: 65536K Description It was long ago when we played the game Red Alert. There is a magic function for the game objects which is called instantaneous transfer. When an object uses this magic fu

POJ 1860 货币兑换 SPFA判正环

Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 20280   Accepted: 7270 Description Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and pe

Currency Exchange---poj1860 ( spfa, 回路,最长路)

题目链接:http://poj.org/problem?id=1860 题解: 两种情况YES,一种是存在正权回路: 一种是求最长路后,实现了增值,也是YES: 用spfa来判断是否存在正权回路,其实spfa是可以用来判断是否存在回路的,不管是正权还是负权,只不过它们松弛的条件不同,正权的话,我们是往dis[]权值增大的方向松弛,负权的话,我们是往dis[]权值减少的方向松弛,然后判断是否存在回路只要看有没有一点入队列的次数大于n就行了用spfa来判断是否存在正权回路,其实spfa是可以用来判断

hdu1317(spfa判断正环+Floyd判断联通)

题意很好理解,判断是否能从起点走到终点,每走到几个点就会获得这个点所代表的能量值,起点时自身带有100能量值. 刚开始写了个裸地spfa,超时了,发现可能存在从起点走不到终点,而且还存在正环,这样程序永远也不会结束,改正后用Floyd判断起点和终点是否联通,然后用spfa求最长路,遇到环中的点时判断,环中的点是否能到达终点,能到达则输出“winnable”,因为可以在正环中获得无限能量值. 不能的话继续做spfa, 并且环中的点不再进入队列,这个换就被破坏了,这样就算图中有多个环也能处理.若没有