用SPFA 解决POJ2240

Posted huotian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用SPFA 解决POJ2240相关的知识,希望对你有一定的参考价值。

                       

Arbitrage

 

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 30790   Accepted: 12761

 

 

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




用spfa解决POJ2240,因学习spfa 的时间较短,犯了不少错误,在代码行中,会注释出来以备察看一些新手可能需要注意的地方,接下来看题意....

题意:给你一些钱币,看你是否能通过汇率转换,赚到更多的钱。

例如给出   :

  我们看第一个样例,1美元可以兑换0.5英镑,1英镑可以兑换10法郎,但1法郎只能兑换0.21美元。

  那么如果你有1美元,我们先兑换成英镑,在兑换成法郎,最后兑换成美元  == 1*0.5*10*0.21=1.05美元,,,明显看出,经过一系列的兑换之后,我们的金钱更多了....那么再看第二个样例, 我们显然可以知道,此题的题意就是让我们求出一条兑换钱币的次序,或者说路径,看是否能有一条路径兑换之后,我们的钱币比原来更多了。

  那么接下来看代码吧..



#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <queue>
#define MAXN 31
int n,m,head[MAXN],vis[MAXN],cnt[MAXN];
char name[31][101];  //用来读入各种货币的名称
using namespace std;
typedef struct

    int start,end;
    int next;
    double w;
 Edge;
Edge edges[10001];
double dis[MAXN];

int Find(char str1[])

    for(int i=1; i<=n; i++)
        if(strcmp(name[i],str1)==0)
            return i;//没有考虑找不到的情况,但是实际上,题目不会给出找不到的货币名称....
    return -1;


bool spaf(int s)

    queue<int>que;
    memset(dis,0,sizeof(dis));
    memset(vis,false,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    vis[s]=dis[s]=1;    //这里一开始学习spfa的时候,还保留着用其他方法的习惯,总给vis[1]置为1 ,,但其实这里应该写成vis[s]=1,不然题目就会出现一些小错误,导致过了样例,却还是wa了
    que.push(s);
    while(!que.empty())
    
        int temp=que.front();
        que.pop();
        vis[temp]=0;
        for(int i=head[temp]; i!=-1; i=edges[i].next)
        int x=edges[i].start,y=edges[i].end;
            double w=edges[i].w;
            if(dis[y]<dis[x]*w)
            
                dis[y]=dis[x]*w;
                if(!vis[y])
                
                    vis[y]=1;
                    if(++cnt[y]>n)    //为了防止某一个节点无限被调用,形成环路,则可以一直赚钱,卡在这里
                        return true;
                    que.push(y);
                
            
        
    
    return false;

int main()

    int len=1;
    char start[101],end[101];
    while(scanf("%d",&n)&&n!=0)
    
        getchar();
        for(int i=1; i<=n; ++i)
            gets(name[i]);
        scanf("%d",&m);
        memset(head,-1,sizeof(head));
        for(int i=0; i<m; ++i)
        
            scanf(" %s %lf %s",start,&edges[i].w,end);
            edges[i].start=Find(start);
            edges[i].end=Find(end);
            edges[i].next=head[edges[i].start];
            head[edges[i].start]=i;
        
        m=0;
        for(int i=1; i<=n; ++i)
        
            if(spaf(i)==true)    
            
                m=1;
                break;
            
        
        if(m)
            printf("Case %d: Yes\n",len++);
        else
            printf("Case %d: No\n",len++);
    
    return 0;

 

以上是关于用SPFA 解决POJ2240的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2240 Arbitrage (spfa判环)

POJ 2240 Arbitrage(SPFA+邻接矩阵)

POJ 2240 (SPFA判正环)

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

POJ-2240 Arbitrage---判断正环+枚举

POJ-2240 -Arbitrage(Bellman)