bellman_ford

bellman_ford(贝尔曼-福特)算法 :因为dijkstra算法不能处理带负权边的图,这时候就可以利用bellman_ford算法。( 设想从我们可以从图中找到一个环路(即从v出发,经过若干个点之后又回到v)且这个环路中所有路径的权值之和为负。那么通过这个环路,环路中任意两点的最 短路径就可以无穷小下去。如果不处理这个负环路,程序就会永远运行下去。 而Bellman-Ford算法具有分辨这种负环路的能力 )

 

时间复杂度 :O(ne)——n是点数,e是边数。如果是邻接阵的话应该就是O(n^3).


联系 :可以优化成SPFA。可以用来写差分约束

 

实现过程 :设G为加权有向图 V是所有结点的集合 E是所有路径的集合 S表示源点 n表示V中所有结点的数目 weight(u,v)表示从结点u  到结点v的路径的权值。 Distanz(v)表示从源点s出发到结点v的最短路径的距离,(或者说是从s到v所有的路径中权值的最小值)。Predecessor(v)表示节点 v的父结点

在Bellman-Ford算法结束之后,可以输出,G是不是包含一个负环路。如果G不包含负环路,那么Distanz就存储了从s出发到所有结点的距离。

Bellman-Ford算法的伪代码如下:
========================================
01 for 每一个结点v 属于 V
02 Distanz(v) := 无穷大, Predecessor(v) := null
03 Distanz(s) := 0,Predecessor(s):= null;

04 循环 n-1 次
05     for 每一条路径 (u,v)属于 E
06         if Distanz(u) + weight(u,v) < Distanz(v)
07         then
08            Distanz(v) := Distanz(u) + weight(u,v)
09            Predecessor(v) := u;

10 for 每一条路径 (u,v)属于 E
11     if Distanz(u) + weight(u,v) < Distanz(v)
12     then
13       中止程序并且返回 “找到负循环”
14 返回
==============================================

 

下面是我用bellman_ford 和静态邻接表写的hdu2544

#include using namespace std; const long point_maxn = 105; const long edge_maxn = 10005; const long lmaxn = 1000000000; int n; int m; struct node { int v; int w; int next; }edge[edge_maxn]; int pre[point_maxn]; int dirs[point_maxn]; void Init() { int i,j; int a,b,c; int Index = 1; memset(pre,-1,sizeof(pre)); for(i=0;i c) { edge[j].w = c; } flag = 1; break; } } if(flag == 1) continue; edge[Index].v = b; edge[Index].w = c; edge[Index].next = pre[a]; pre[a] = Index++; swap(a,b); for(flag=0,j=pre[a];j!=-1;j=edge[j].next) { if(edge[j].v == b) { if(edge[j].w > c) { edge[j].w = c; } break; } } edge[Index].v = b; edge[Index].w = c; edge[Index].next = pre[a]; pre[a] = Index++; } } int bellman_ford() { int i,j,k; fill(dirs,dirs+point_maxn,lmaxn); int start = 1; int end = n; dirs[start] = 0; for(i=0;i dirs[s] + edge[k].w) { dirs[e] = dirs[s] + edge[k].w; } } } } for(j=1;j<=n;j++) { for(k=pre[j];k!=-1;k=edge[k].next) { int s = j; int e= edge[k].v; if(dirs[e] > dirs[s] + edge[k].w) { return 0; } } } return 1; } void print() { if(!bellman_ford()) { printf("-1/n"); } else { printf("%d/n",dirs[n]); } } int main() { while(scanf("%d%d",&n,&m)!=EOF && (n!=0 || m!=0)) { Init(); print(); } return 0; }

 

你可能感兴趣的:(算法,null,优化,c,存储)