最短路问题(short-path problem)是网络理论解决的典型问题之一,可用来解决管路铺设、线路安装、厂区布局和设备更新等实际问题。基本内容是:若网络中的每条边都有一个数值(长度、成本、时间等),则找出两节点(通常是源节点和阱节点)之间总权和最小的路径就是最短路问题。
解决最短路问题的Floyd算法:
Floyd算法:
又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法。
算法步骤:
(1)从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
(2)对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。如果是,更新它。把图用邻接矩阵G表示出来,如果从Vi到Vj有路可达,则G[i][j]=d,d表示该路的长度;否则G[i][j]=无穷大。定义一个矩阵D用来记录所插入点的信息,D[i][j]表示从Vi到Vj需要经过的点,初始化D[i][j]=j。把各个顶点插入图中,比较插点后的距离与原来的距离,G[i][j] = min( G[i][j], G[i][k]+G[k][j] ),如果G[i][j]的值变小,则D[i][j]=k。在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。
例:已知有6个村子,相互间道路如图所示。欲合建一所小学,已知A处有小学生50人,B处40人,C处60人,D处20人,E处70人,F处90人,问学校应建在哪个村子,使得学生上学最方便。
程序代码:
(1)road函数的m文件:
function minroad=road(u,s,begin_node,end_node)
minroad=[];
S=s;
k=S(begin_node,end_node);
if(k~=begin_node)&&(k~=end_node)
minroad=[begin_node,k];
end
if(k==begin_node)||(k==end_node)
fprintf('输入错误!');
end
while(k~=end_node)
k=S(k,end_node);
minroad=[minroad,k];
end
end
(2)Floyd算法的m文件:
d=[0 2 7 Inf Inf Inf
2 0 4 6 8 Inf
7 4 0 1 3 Inf
Inf 6 1 0 1 6
Inf 8 3 1 0 3
Inf Inf Inf 6 3 0];
n=length(d);
U=d;
S=zeros(n,n);
for i=1:n
for j=1:n
S(i,j)=j;
end
end
for i=1:n
for j=1:n
for m=1:n
if U(i,j)>U(i,m)+U(m,j)
S(i,j)=S(i,m);
U(i,j)=U(i,m)+U(m,j);
end
end
end
end
people=[50 40 60 20 70 90];
distance=[inf inf inf inf inf inf];
for i=1:n
distance(i)=U(i,:)*people';
end
S
U
people
distance
[min_distance,village]=min(distance)
begin_node=input('输入起始节点:begin=')
end_node=input('输入终止节点:end=')
minroad=road(U,S,begin_node,end_node)
运行结果:
>> Floyd
S =
1 2 2 2 2 2
1 2 3 3 3 3
2 2 3 4 4 4
3 3 3 4 5 5
4 4 4 4 5 6
5 5 5 5 5 6
U =
0 2 6 7 8 11
2 0 4 5 6 9
6 4 0 1 2 5
7 5 1 0 1 4
8 6 2 1 0 3
11 9 5 4 3 0
people =
50 40 60 20 70 90
distance =
2130 1670 1070 1040 1050 1500
min_distance =
1040
village =
4
输入起始节点:begin=1
begin_node =
1
输入终止节点:end=6
end_node =
6
minroad =
1 2 3 4 5 6
综上所述,学校应建在D村,最短路为1040。