题意:Arbitrage问题(套汇)。给定若干币种及一些币种转换的汇率,问能否有套汇的可能。
思路:如果以币种为定点,汇率为边建图,则相当于求一个圈,其上权值乘积大于1。将权值取对数再取负,变成求有向图负环。用floyd算法即可。(直接上Floyd,三层循环中判断直接用乘法也OK)。另外用spfa判断应该也行,只需将每个点都入队一次。
#include <stdio.h>
#include <string.h>
#include <math.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define N 35
char name[N][128];
int c=1,n,m;
double g[N][N];
int find(char* x){
int i;
for(i = 1;i<=n;i++)
if(!strcmp(name[i], x))
return i;
return -1;
}
int main(){
while(scanf("%d",&n) && n){
int i,j,k,a,b;
char s[128],t[128];
double w;
for(i = 1;i<=n;i++)
for(j = 1;j<=n;j++)
g[i][j] = 0x3fffffff;
for(i = 1;i<=n;i++)
scanf("%s",name[i]);
scanf("%d",&m);
for(i = 0;i<m;i++){
scanf("%s %lf %s",s,&w,t);
a = find(s);
b = find(t);
g[a][b] = -log10(w);
}
for(k = 1;k<=n;k++)
for(i = 1;i<=n;i++)
for(j = 1;j<=n;j++)
g[i][j] = min(g[i][j],g[i][k]+g[k][j]);
for(i = 1;i<=n;i++)
if(g[i][i] < 0)
break;
if(i<=n)
printf("Case %d: Yes\n",c++);
else
printf("Case %d: No\n",c++);
}
return 0;
}