标签:style blog color os io for ar 问题 div
题意:
给出一些货币和货币之间的兑换比率,问是否可以使某种货币经过一些列兑换之后,货币值增加。
举例说就是1美元经过一些兑换之后,超过1美元。可以输出Yes,否则输出No。
分析:
首先我们要把货币之间的关系转化成一张图。转化时,用STL里面的map很方便。
为每种货币分配一个序列号,一个序列号代表了一个图中间的NODE,而node之间的edge用汇率表示。
一开始用Dijkstra算法做,死活AC不了,网友给的理由是:
由于Dijkstra算法不能处理带有负权值的最短路,但此题中,两种货币之间的兑换比率可能小于1,相当于这条路径的权值为负
前车之鉴,WA的代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<string.h> 5 #include<string> 6 #include<map> 7 using namespace std; 8 #define maxn 31 9 #define inf 0x3f3f3f3f 10 double edges[maxn][maxn]; 11 double dist[maxn]; 12 typedef pair<int,int> P; 13 void init(){ 14 for(int i=1;i<maxn;i++) 15 for(int j=1;j<maxn;j++) 16 edges[i][j]=(i==j?1:0);//1代表等价价换,0:代表无法交换 17 } 18 19 void dijkstra(int s,int n){ 20 bool visited[maxn]; 21 memset(visited,0,sizeof(visited)); 22 visited[s]=true; 23 for(int i=1;i<=n;i++) 24 dist[i]=edges[s][i]; 25 for(int i=1,u;i<=n;i++){ 26 double max=-1; 27 for(int j=1;j<=n;j++) 28 if(!visited[j]&&dist[j]>max){ 29 max=dist[j]; u=j; 30 } 31 32 visited[u]=true; 33 for(int j=1;j<=n;j++){ 34 if(dist[u]*edges[u][j]>dist[j]) 35 dist[j]=dist[u]*edges[u][j]; 36 } 37 } 38 } 39 40 int main(){ 41 //freopen("in.txt","r",stdin); 42 int n,cases=0; 43 while(scanf("%d",&n)!=EOF && n){ 44 cases++; 45 init(); 46 map<string,int> ma; 47 string s,t; 48 for(int i=1;i<=n;i++){ 49 cin>>s; 50 ma.insert(make_pair(s,i)); 51 } 52 int m; 53 double tmp; 54 scanf("%d",&m); 55 while(m--){ 56 cin>>s>>tmp>>t; 57 edges[ma[s]][ma[t]]=tmp; 58 } 59 60 dijkstra(1,n); 61 printf("Case %d: ",cases); 62 if(dist[1]>1.0) 63 printf("Yes\n"); 64 else 65 printf("No\n"); 66 } 67 }
最后写了一个Floyd的代码版本,结果一下子就过了,我只能默默的哭了
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<string.h> 5 #include<string> 6 #include<map> 7 using namespace std; 8 #define maxn 31 9 #define inf 0x3f3f3f3f 10 double edges[maxn][maxn]; 11 void init(){ 12 for(int i=1;i<maxn;i++) 13 for(int j=1;j<maxn;j++) 14 edges[i][j]=(i==j?1:0);//1:代表等价交换,0:代表无法交换 15 } 16 17 void floyd_warshall(int s,int n){ 18 for(int k=1;k<=n;k++){ 19 for(int i=1,u;i<=n;i++){ 20 for(int j=1;j<=n;j++){ 21 if(edges[i][k]*edges[k][j]>edges[i][j])//如果找到了更好的交换方案 22 edges[i][j]=edges[i][k]*edges[k][j]; 23 } 24 } 25 } 26 } 27 28 int main(){ 29 //freopen("in.txt","r",stdin); 30 int n,cases=0; 31 while(scanf("%d",&n)!=EOF && n){ 32 cases++; 33 init(); 34 map<string,int> ma; 35 string s,t; 36 for(int i=1;i<=n;i++){ 37 cin>>s; 38 ma.insert(make_pair(s,i)); 39 } 40 int m; 41 double tmp; 42 scanf("%d",&m); 43 while(m--){ 44 cin>>s>>tmp>>t; 45 edges[ma[s]][ma[t]]=tmp; 46 } 47 48 dijkstra(1,n); 49 printf("Case %d: ",cases); 50 /*for(int i=1,u;i<=n;i++){ 51 for(int j=1;j<=n;j++){ 52 printf("%.2f ",edges[i][j]); 53 } 54 printf("\n"); 55 }*/ 56 if(edges[1][1]>1.0) 57 printf("Yes\n"); 58 else 59 printf("No\n"); 60 } 61 }
【问题】:Folyd算法能处理包含负权边的图吗?
答案是可以的。Floyd-Warshall算法和Bellman-Ford算法一样,可以处理边是负数的情况。
---《挑战程序设计竞赛》 P.103
标签:style blog color os io for ar 问题 div
原文地址:http://www.cnblogs.com/ZJUT-jiangnan/p/3932844.html