Bellman-ford算法 poj2240

Bellman-ford算法的递推公式应该改为(求源点v0到各顶点v的最短路径):

初始:dist(0)[v]=inf,dist(0)[v0]=0,v0是源点,v≠v0
递推:对每条边(u,v),dist(k)[v]=min{dist(k-1)[v],dist(k-1)[v]+w(u,v)};k=1,2,3...

View Code
 1 void bellman(int v0){
 2     int i,k;
 3     for(i=0;i<n;i++){
 4         dist[i]=inf;
 5         path[i]=-1;
 6     }
 7     dist[v0]=0;
 8     for(k=1;k<n;k++){
 9         for(i=0;i<m;i++){
10             if(dist[edges[i].u]!=INF&&edges[i].w+dist[edge[i].u]<dist[edges[i].v]){
11                 dist[edges[i].v]=edges[i].w+dist[edge[i].u];
12                 path[edges[i].v]=edges[i].u;
13             }
14         }
15     }
16 }

Bellman-ford算法判断负权值回路:
如果存在负权值回路,则最短路径不存在,因为可以重复走这个回路使得路径无穷小,在Bellman-ford算法中,判断是否存在从源点可达的负权值回路的方法如下:
再求出dist(n-1)[v]之后,再对每一条边<u,v>判断一下:加入这条边会不会使得顶点v的最短路径再缩小,即判断
dist[u]+edge[u][v]<dist[v]
是否成立,如果成立,则说明存在从源点可达的负权值回路。

代码如下:

View Code
 1 for(i=0;i<n;i++){
 2     for(j=0;j<n;j++){
 3         if(edge[i][j]<inf&&dist[i]+edge[i][j]<dist[j])
 4             return 0;
 5     }
 6 }
 7 return 1;
 8 ///或者是以下代码
 9 for(i=0;i<m;i++){
10     if(dist[edge[i].u]!=inf&&edge[i].w+dist[edge[i].u]<dist[edge[i].v])
11         return 0;
12 }
13 return 1;

Bellman-ford算法与Dijkstra算法相比,可以处理有负权值的边的最短路问题,在求解过程中的区别是:

①Dijkstra在求解过程中,源点到集合S内各顶点的最短路径一旦求出,则不变化了,修改的仅仅是从源点到T集合中个顶点的最短路径长度。
②Bellman-ford算法在求解过程中,每次循环每个顶点的dist[]值都有可能要修改,也就是说源点到各顶点最短路径长度一直要到Bellman-ford算法结束才确定下来。

 

poj2240题意:比如1美元可以兑换0.5英镑,1英镑可以兑换10.0法郎,1法郎可以兑换0.21美元,这样1美元可以转换成1*0.5*0.21=1.05美元,给出兑换率,算出是否存在这种Arbitrage。
思路:求到本身的最长路,可以用floyd,也可以用Bellman-ford~

View Code
 1 #include <map>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #include <iostream>
 5 using namespace std;
 6 const int N=40;
 7 int n,m,flag;
 8 double dist[N];
 9 struct edge{
10     int a,b;
11     double c;
12 }e[N*N];
13 void bellman(int v0){
14     int i,k;
15     memset(dist,0,sizeof(dist));
16     dist[v0]=1;
17     for(k=1;k<=n;k++){
18         for(i=0;i<m;i++){
19             if(dist[e[i].a]*e[i].c>dist[e[i].b]){
20                 dist[e[i].b]=dist[e[i].a]*e[i].c;
21             }
22         }
23     }
24     if(dist[v0]>1.0) flag=1;
25 }
26 int main(){
27     char ch[100];
28     int i,j,k=0;
29     while(scanf("%d",&n)!=EOF&&n){
30         map<string,int>M;
31         for(i=0;i<n;i++){
32             scanf("%s",ch);
33             M[ch]=i;
34         }
35         scanf("%d",&m);
36         for(i=0;i<m;i++){
37             scanf("%s %lf",ch,&e[i].c);
38             e[i].a=M[ch];
39             scanf("%s",ch);
40             e[i].b=M[ch];
41         }
42         flag=0;
43         for(i=0;i<n;i++){
44             bellman(i);
45             if(flag) break;
46         }
47         printf("Case %d: ",++k);
48         if(flag) puts("Yes");
49         else puts("No");
50     }
51     return 0;
52 }

 

posted @ 2013-02-25 17:13  _sunshine  阅读(366)  评论(2编辑  收藏  举报