这道题求一条含环的最长路,所以SPFA和Dijkstra算法不能用,选用Bellman-Ford或者Floyd。
/*
ID:slowlight
PROG:Arbitrage
LANG:C++
DATE:2013-9-5
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
using namespace std;
typedef struct{
int name;
float value;
}Point;
char iHash[31][30];
float d[31][31];
float f[31][31];
bool visit[31];
void add_edge( char * buf, int n );
int main()
{
freopen("input.in", "r", stdin);
freopen("output.out", "w", stdout);
int currency_num;
int M;
int case_cnt = 0;
const int buf_size = 100;
char buf[ buf_size ];
cin >> currency_num;
do
{
// initialize
bool isFind = false;
for(int i=0;i<31;i++)
for(int j=0;j<31;j++)
{
d[i][j] = 0;
}
case_cnt++;
for(int i=0;i<currency_num;i++)
cin >> iHash[i];
cin >> M;
getchar();
while( M-- )
{
cin.getline(buf, buf_size);
//add a exchange way
add_edge( buf, currency_num );
}
// floyd initialize
for(int i=0;i<31;i++)
for(int j=0;j<31;j++)
if( d[i][j] > 0 )
{
f[i][j] = d[i][j];
}
else if( i == j )
f[i][j] = 1.0;
else
f[i][j] = -1;
for(int i=0;i<currency_num;i++)
for(int j=0;j<currency_num;j++)
for(int k=0;k<currency_num;k++)
if( f[i][j] < f[i][k] * f[k][j] )
f[i][j] = f[i][k] * f[k][j];
for(int i=0;i<currency_num;i++)
if( f[i][i] > 1.0 )
{
isFind = true;
break;
}
if( isFind )
cout << "Case " << case_cnt << ": Yes" << endl;
else
cout << "Case " << case_cnt << ": No" << endl;
cin >> currency_num;
}while( currency_num );
return 0;
}
void add_edge( char * buf , int n )
{
char * str1 = buf;
char * str2 = buf + strlen( buf ) - 1;
int pt1;
int pt2;
float v;
while( ( *str2 ) != ' ' )
str2--;
str2++;
for(pt1=0;pt1<n;pt1++)
if( strncmp( iHash[pt1], str1 , strlen( iHash[pt1] )) == 0 )
break;
for(pt2=0;pt2<n;pt2++)
if( strcmp( iHash[pt2], str2 ) == 0 )
break;
while( (*str1) != ' ' )
str1++;
str1++;
v = atof( str1 );
d[pt1][pt2] = v;
}
参考别人的代码(http://blog.csdn.net/lyy289065406/article/details/6645857),用了map后简洁多了:
/*
ID:slowlight
PROG:Arbitrage
LANG:C++
DATE:2013-9-5
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <string>
using namespace std;
float d[31][31];
float f[31][31];
map <string, int> mymap;
int main()
{
freopen("input.in", "r", stdin);
freopen("output.out", "w", stdout);
int currency_num;//num of nodes
int M;//num of edges
int case_cnt = 0;// number of case
float value;// value of edge
string buf;//buffer
cin >> currency_num;
do
{
/*initialize*/
bool isFind = false;
case_cnt++;
for(int i=0;i<31;i++)
for(int j=0;j<31;j++)
{
d[i][j] = 0;
}
/*input*/
for(int i=0;i<currency_num;i++) //construct maps
{
cin >> buf;
mymap[buf] = i;
}
cin >> M;
getchar();//eat a space
while( M-- )
{
int pt1;
int pt2;
cin >> buf;
pt1 = mymap[buf];
cin >> value;
cin >> buf;
pt2 = mymap[buf];
d[pt1][pt2] = value;
}
/* floyd initialize */
for(int i=0;i<31;i++)
for(int j=0;j<31;j++)
if( d[i][j] > 0 )
{
f[i][j] = d[i][j];
}
else if( i == j )
f[i][j] = 1.0;
else
f[i][j] = -1;
/*floyd*/
for(int i=0;i<currency_num;i++)
for(int j=0;j<currency_num;j++)
for(int k=0;k<currency_num;k++)
if( f[i][j] < f[i][k] * f[k][j] )
f[i][j] = f[i][k] * f[k][j];
for(int i=0;i<currency_num;i++)
if( f[i][i] > 1.0 )
{
isFind = true;
break;
}
/*print*/
if( isFind )
cout << "Case " << case_cnt << ": Yes" << endl;
else
cout << "Case " << case_cnt << ": No" << endl;
cin >> currency_num;
}while( currency_num );
return 0;
}