http://poj.org/problem?id=2240
钱币来回兑换。
大家都知道先构图,然后看图中的某个节点会不会经过一圈之后到达自己,并且路径上的权值乘积大于1。
显然是最短路的反面,最长路;同时不能使用单源最短路dijkstra算法。
所以使用floyd多源最短路,不过这里注意比较条件,要“最长路”。
从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。
# include<iostream>
# include<stdio.h>
# include<string.h>
# include<string>
# include<map>
using namespace std;
# define N 40
map<string, int> mp;
double data[N][N];
int main()
{
int n,m,i,j,k,c;
double rate;
string c1,c2;
c=0;
//while(~scanf("%d",&n))=========逗了。。。
while(true)
{
cin>>n;
if(n==0)
{
break;
}
mp.clear();
memset(data,0.0,sizeof(data));
for(i=1;i<=n;i++)
{
cin>>c1;
mp[c1]=i;
data[i][i]=1.0;
}
cin>>m;
for(i=1;i<=m;i++)
{
cin >> c1 >> rate >> c2;
if(rate>data[mp[c1]][mp[c2]])
{
data[mp[c1]][mp[c2]]=rate;
}
}
for(i=1;i<=n;i++)
{
for(j=1; j<=n;j++)
{
for(k=1;k<=n;k++)
{
if (data[i][j] < data[i][k]*data[k][j]) //find max path
{
data[i][j] = data[i][k]*data[k][j];//max path length
}
}
}
}
j=0;
for(i=1;i<=n;i++)
{
if(data[i][i]>1.0)//profit
{
j=1;
break;
}
}
if(j==1)
{
cout<<"Case "<<++c<<": Yes"<<endl;
}
else
{
cout<<"Case "<<++c<<": No"<<endl;
}
}
return 0;
}
这里有个关于dijkstra算法和floyd算法的介绍,很不错:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html