用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#include #include <string.h> #include #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] 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 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; }