单源最短路径的求法
来源:互联网 发布:吊带袜天使结局 知乎 编辑:程序博客网 时间:2024/04/30 08:09
2.最短路径
算法思想:
设图中有n个结点,设置一个集会u,存放已经求出最短路径的结点(初始时u中的元素是源点),v-u是尚未确定最短路径的顶点的集合。每次从v-u集合中找这样一个结点 best_j:best_j是u集合中结点的邻接点,到源点的距离最短(等于到父结点的距离加上父结点到源点的距离)。然后把该best_j置入u集合中,直到u=v。
A.标号法求解单源点最短路径:
var
a:array[1..maxn,1..maxn] of integer;
b:array[1..maxn] of integer; {b[i]指顶点i到源点的最短路径}
mark:array[1..maxn] of boolean;
var
a:array[1..maxn,1..maxn] of integer;
b:array[1..maxn] of integer; {b[i]指顶点i到源点的最短路径}
mark:array[1..maxn] of boolean;
procedure bhf;
var
best,best_j:integer;
begin
fillchar(mark,sizeof(mark),false);
mark[1]:=true; b[1]:=0;{1为源点}
repeat
best:=0;
for i:=1 to n do{双重循环,找到这样一个结点:所有已经标号的结点(包括源点)的邻接点中,到源点距离最短的点,j点到源点的距离是她到父节点的距离加上父节点到源点的距离,这里与prim算法求最小生成树的思想有点不同,prim是所有已经标号的结点的邻接点中,到父节点距离最短的点,}
If mark[i] then {对每一个已计算出最短路径的点}
for j:=1 to n do
if (not mark[j]) and (a[i,j]>0) then{j未标号,是i的邻接点}
if (best=0) or (b[i]+a[i,j]<BEST) THEN {因为b[1]=0,所以best的第一个值是b[I,j]值 }
var
best,best_j:integer;
begin
fillchar(mark,sizeof(mark),false);
mark[1]:=true; b[1]:=0;{1为源点}
repeat
best:=0;
for i:=1 to n do{双重循环,找到这样一个结点:所有已经标号的结点(包括源点)的邻接点中,到源点距离最短的点,j点到源点的距离是她到父节点的距离加上父节点到源点的距离,这里与prim算法求最小生成树的思想有点不同,prim是所有已经标号的结点的邻接点中,到父节点距离最短的点,}
If mark[i] then {对每一个已计算出最短路径的点}
for j:=1 to n do
if (not mark[j]) and (a[i,j]>0) then{j未标号,是i的邻接点}
if (best=0) or (b[i]+a[i,j]<BEST) THEN {因为b[1]=0,所以best的第一个值是b[I,j]值 }
BEGIN
best:=b[i]+a[i,j]; best_j:=j;
end;
if best>0 then begin
b[best_j]:=best;mark[best_j]:=true;
end;
until best=0;
end;{bhf}
best:=b[i]+a[i,j]; best_j:=j;
end;
if best>0 then begin
b[best_j]:=best;mark[best_j]:=true;
end;
until best=0;
end;{bhf}
总结:每次找best_j都要双重循环,原因是没有把未标号结点当前到源点的最短距离保存起来,还有优化的空间。
C. Dijkstra 算法:
var
a:array[1..maxn,1..maxn] of integer;
b,pre:array[1..maxn] of integer; {pre[i]指最短路径上I的前驱结点}
mark:array[1..maxn] of boolean;
procedure dijkstra(v0:integer);
begin
fillchar(mark,sizeof(mark),false);
for i:=1 to n do begin
d[i]:=a[v0,i];
if d[i]<>0 then pre[i]:=v0 else pre[i]:=0;
end;
mark[v0]:=true;
repeat {每循环一次加入一个离1集合最近的结点并调整其他结点的参数}
min:=maxint; u:=0; {u记录离1集合最近的结点}
for i:=1 to n do
if (not mark[i]) and (d[i]<MIN) THEN
a:array[1..maxn,1..maxn] of integer;
b,pre:array[1..maxn] of integer; {pre[i]指最短路径上I的前驱结点}
mark:array[1..maxn] of boolean;
procedure dijkstra(v0:integer);
begin
fillchar(mark,sizeof(mark),false);
for i:=1 to n do begin
d[i]:=a[v0,i];
if d[i]<>0 then pre[i]:=v0 else pre[i]:=0;
end;
mark[v0]:=true;
repeat {每循环一次加入一个离1集合最近的结点并调整其他结点的参数}
min:=maxint; u:=0; {u记录离1集合最近的结点}
for i:=1 to n do
if (not mark[i]) and (d[i]<MIN) THEN
BEGIN
u:=i; min:=d[i];
end;
if u<>0 then begin
mark[u]:=true;
for i:=1 to n do
if (not mark[i]) and (a[u,i]+d[u]<D[I]) THEN{如果未标号的结点经过新标号的结点到源点的距离最短,则调整,这样d集合总是未标号结点到源点的最短距离}
u:=i; min:=d[i];
end;
if u<>0 then begin
mark[u]:=true;
for i:=1 to n do
if (not mark[i]) and (a[u,i]+d[u]<D[I]) THEN{如果未标号的结点经过新标号的结点到源点的距离最短,则调整,这样d集合总是未标号结点到源点的最短距离}
BEGIN
d[i]:=a[u,i]+d[u];
pre[i]:=u;
end;
end;
until u=0;
end;
d[i]:=a[u,i]+d[u];
pre[i]:=u;
end;
end;
until u=0;
end;
- 单源最短路径的求法
- AOE网中关键路径的一般求法
- 欧拉环、欧拉路径的判定和求法
- 欧拉环、欧拉路径的判定和求法
- 数字三角最大路径求法
- 无权最短路径的求法--图的广度优先搜索
- 数素的求法
- 逆矩阵的求法!
- 质数的最快求法
- 素数的求法
- 孪生素数的求法
- 圆周率PI的求法
- 大数阶乘的求法
- 最大团的求法
- 特征向量的数值求法
- c++ sinx的求法
- 素数的求法
- 格雷码的求法
- 方便与随便
- LoanBroker教程
- 记忆化搜索例题
- 树知识回顾
- c#抽象工厂实例
- 单源最短路径的求法
- C/C++中的日期和时间 (转自zhanjun.net)
- 中国军队在用银河麒麟,那美国军队在用什么操作系统呢?
- C/C++头文件一览
- Oracle基本操作
- javabean
- 微软的工作评定FAQ
- oracle基本操作语句(适合初学者)
- Windows的右键菜单更新