【变形Floyd】HDU-1217 Arbitrage

来源:互联网 发布:手机号绑定软件查询 编辑:程序博客网 时间:2024/06/07 07:55

原题链接点击打开链接

弗洛伊德用于求最短路。

但在有些情况下,由于弗洛伊德核心代码的判定条件十分开放和明朗,只要通过对弗洛伊德的结构进行一些变换,便可以解决除最短路之外的相应问题。

在本题中,交换利率可以形象地理解为在若干个点中的一条路径。该路径在经过几个点之后,返回起始点。

在路径a->b途中,用路径的权值代表a兑换b的利率,于是,只要将路径的权值相乘,即是该路径最后得到的兑换率。

通过该方法,只要在最后比较各点回到自己的路径的最大利率之积(最短路是最小权值之和),判断是否有回到自己时利率之积大于1的值,如果有,那么这组数据可以通过兑换货币牟利。

#include<cstdio>#include<cstring>#include<map>using namespace std;const int maxn=35;double dis[maxn][maxn];int n,m;void Floyd(){      for(int k=1;k<=n;k++)            for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)            if(dis[i][k]*dis[k][j]>dis[i][j])//弗洛伊德由求和变形为乘积            dis[i][j]=dis[i][k]*dis[k][j];}int main(){      char input[50];      char a[50],b[50];      double v;      map<string,int>name;//用map给各个名称标号      int iter;      int counter=1;      while(scanf("%d",&n)!=EOF&&n)      {            memset(dis,0,sizeof(dis));            for(int i=1;i<=n;i++)                  dis[i][i]=1;            name.clear();            iter=1;            for(int i=0;i<n;i++)            {                  scanf("%s",input);                  name[input]=iter++;            }            scanf("%d",&m);            for(int i=0;i<m;i++)            {                  scanf("%s%lf%s",a,&v,b);                  dis[name[a]][name[b]]=v;            }            Floyd();            int flag=0;            printf("Case %d: ",counter++);            for(int i=1;i<=n;i++)                  if(dis[i][i]>1)                  {                        flag=1;                        break;                  }            if(flag)                  printf("Yes\n");            else                  printf("No\n");      }      return 0;}


原创粉丝点击