最小树最短路程序.docx
《最小树最短路程序.docx》由会员分享,可在线阅读,更多相关《最小树最短路程序.docx(15页珍藏版)》请在冰豆网上搜索。
最小树最短路程序
Kruskal算法(避圈法)
clc;clear;
a(1,2)=50;a(1,3)=60;a(2,4)=65;a(2,5)=40;
a(3,4)=52;a(3,7)=45;a(4,5)=50;a(4,6)=30;
a(4,7)=42;a(5,6)=70;
[i,j,b]=find(a);%生成三个列向量
data=[i';j';b'];index=data(1:
2,:
);
loop=length(a)-1;
result=[];
whilelength(result)temp=min(data(3,:
));
flag=find(data(3,:
)==temp);
flag=flag
(1);
v1=index(1,flag);v2=index(2,flag);
ifv1~=v2
result=[result,data(:
flag)];
end
index(find(index==v2))=v1;
data(:
flag)=[];
index(:
flag)=[];
end
result
Prim算法(顶点扩充法)
clc;clear;%清空命令窗口,清空内存
a=zeros(7);
a(1,2)=50;a(1,3)=60;
a(2,4)=65;a(2,5)=40;
a(3,4)=52;a(3,7)=45;
a(4,5)=50;a(4,6)=30;a(4,7)=42;
a(5,6)=70;
a=a+a';a(a==0)=inf;
result=[];p=1;tb=2:
length(a);%边的个数比顶点数少一
whilesize(result,2)~=length(a)-1
temp=a(p,tb)
temp=temp(:
)%将temp转化成一维列数组
d=min(temp)
[jb,kb]=find(a(p,tb)==d);
j=p(jb
(1));k=tb(kb
(1));
result=[result,[j;k;d]];p=[p,k];
tb(find(tb==k))=[];%将顶点k从选择顶点中去掉
end
result
从起点sb到终点db通用的Dijkstra标号算法程序
function[mydistance,mypath]=mydijkstra(a,sb,db);
%输入:
a—邻接矩阵,a(i,j)是指i到j之间的距离,可以是有向的
%sb—起点的标号,db—终点的标号
%输出:
mydistance—最短路的距离,mypath—最短路的路径
n=size(a,1);visited(1:
n)=0;
distance(1:
n)=inf;distance(sb)=0;%起点到各顶点距离的初始化
visited(sb)=1;u=sb;%u为最新的P标号顶点
parent(1:
n)=0;%前驱顶点的初始化
fori=1:
n-1
id=find(visited==0);%查找未标号的顶点
forv=id
ifa(u,v)+distance(u)distance(v)=distance(u)+a(u,v);%修改标号值
parent(v)=u;
end
end
temp=distance;
temp(visited==1)=inf;%已标号点的距离换成无穷
[t,u]=min(temp);%找标号值最小的顶点
visited(u)=1;%标记已经标号的顶点
end
mypath=[];
ifparent(db)~=0%如果存在路!
t=db;mypath=[db];
whilet~=sb%从终点db开始回溯
p=parent(t);
mypath=[pmypath];
t=p;
end
end
mydistance=distance(db);
例题某公司在六个城市
中有分公司,从
到
的直接航程票价记在下述矩阵的(i,j)位置上。
(∞表示无直接航路),请帮助该公司设计一张城市
到其它城市间的票价最便宜的路线图。
LINGO的Floyd算法程序如下
model:
sets:
nodes/c1..c6/;
link(nodes,nodes):
w,path;!
path标志最短路径上走过的顶点;
endsets
data:
path=0;
w=0;
enddata
calc:
w(1,2)=50;w(1,4)=40;w(1,5)=25;w(1,6)=10;
w(2,3)=15;w(2,4)=20;w(2,6)=25;
w(3,4)=10;w(3,5)=20;
w(4,5)=10;w(4,6)=25;w(5,6)=55;
@for(link(i,j):
w(i,j)=w(i,j)+w(j,i));
@for(link(i,j)|i#ne#j:
w(i,j)=@if(w(i,j)#eq#0,10000,w(i,j)));
@for(nodes(k):
@for(nodes(i):
@for(nodes(j):
tm=@smin(w(i,j),w(i,k)+w(k,j));
path(i,j)=@if(w(i,j)#gt#tm,k,path(i,j));w(i,j)=tm)));
endcalc
end
求解最短路问题的数学规划法
取决策变量为
,当
,说明弧
位于顶点
到顶点
的最短路上,否则
。
s.t
例在下图中,用点表示城市,现有
共7个城市。
点与点之间的连线表示城市间有道路相连。
连线旁的数字表示道路的长度。
现计划从城市
到城市
铺设一条天然气管道,请设计出最小长度管道铺设方案。
基于数学规划求解最短路的LINGO代码
model:
sets:
cities/A,B1,B2,C1,C2,C3,D/;
roads(cities,cities)/AB1,AB2,B1C1,B1C2,B1C3,B2C1,
B2C2,B2C3,C1D,C2D,C3D/:
w,x;
endsets
data:
w=24331231134;
enddata
n=@size(cities);!
城市的个数;
min=@sum(roads:
w*x);
@for(cities(i)|i#ne#1#and#i#ne#n:
@sum(roads(i,j):
x(i,j))=@sum(roads(j,i):
x(j,i)));
@sum(roads(i,j)|i#eq#1:
x(i,j))=1;
@sum(roads(i,j)|j#eq#n:
x(i,j))=1;
end
求最大流问题的Ford-Fulkerson标号算法
function[fwfNo]=fofuf(C,f1)
%C表示弧上的容量
%f1表示弧上现有的流量函数,默认情况下为0
%f表示最大流
%wf表示最大流量
%No标号函数,由此可得最小割
%注:
待求最大流的源为第一个顶点,汇为最后一个顶点
n=length(C)
ifnargin==1;
f=zeros(n,n);
else
f=f1;
end
No=zeros(1,n);
d=zeros(1,n);
while
(1)
No
(1)=n+1;
d
(1)=Inf;%给发点vs标号
while
(1)%标号过程
pd=1;
for(i=1:
n)
if(No(i))%选择一个已标号的vi
for(j=1:
n)
if(No(j)==0&f(i,j)No(j)=i;d(j)=C(i,j)-f(i,j);
pd=0;
if(d(j)>d(i))
d(j)=d(i);
end
elseif(No(j)==0&f(j,i)>0)%对于未给标号的点vj,当vi-vj为非零流弧时
No(j)=-i;d(j)=C(j,i)
;pd=0;
if(d(j)>d(i))
d(j)=d(i);
end
end
end
end
end
if(No(n)|pd)
break;
end
end%若收点vt得到标号或者无法标号,则终止标号过程
if(pd)
break;
end%vt未得到标号,f已是最大流,算法终止
dvt=d(n);t=n;%进入调整过程,dvt表示调整量
while
(1)
if(No(t)>0)
f(No(t),t)=f(No(t),t)+dvt;%前向弧调整
elseif(No(t)<0)
f(No(t),t)=f(No(t),t)-dvt;%后向弧调整
end
if(No(t)==1)
for(i=1:
n)
No(i)=0;d(i)=0;
End
break
end%当t的标号为vs时,终止调整过程
t=No(t);
end%继续调整前一段弧上的流f
end
wf=0;
for(j=1:
n)%计算最大流量
wf=wf+f(1,j);
end
f;%显示最大流
wf;%显示最大流量
No;%显示标号,由此可得最小割
end
例求下图所示网络的最大流
C=[05430000;
00005300;
00000320;
00000020;
00000004;
00000003;
00000005;
00000000];
[qwe]=fofuf(C)
最小费用最大流问题
function[fwfzwf]=BGf(C,b)
%C表示弧容量矩阵
%b表示弧上单位流量的费用
%f表示最小费用最大流矩阵
%wf表示最大流量
%zwf表示最小费用
n=size(C,2);
wf=0;wf0=Inf;%wf表示最大流量,wf0表示预定的流量值
f=zeros(n,n);%取初始可行流f为零流
while
(1)
a=ones(n,n)*inf;
for(i=1:
n)
a(i,i)=0;
end%构造有向赋权图a
for(i=1:
n)
for(j=1:
n)
if(C(i,j)>0&f(i,j)==0)
a(i,j)=b(i,j);
elseif(C(i,j)>0&f(i,j)==C(i,j))
a(j,i)=-b(i,j);
elseif(C(i,j)>0)
a(i,j)=b(i,j);
a(j,i)=b(i,j);
end
end
end
for(i=2:
n)
p(i)=Inf;s(i)=i;
end%用Floyd算法求最短路,赋初值
for(k=1:
n)
pd=1;%求有向赋权图中vs到vt的最短路
for(i=2:
n)
for(j=1:
n)
if(p(i)>p(j)+a(j,i))
p(i)=p(j)+a(j,i);s(i)=j;pd=0;
end
end
end
if(pd)
break;
end
end%求最短路的Floyd算法结束
if(p(n)==Inf)
break;
end%不存在vs到vt的最短路,算法终止
%注意在求最小费用最大流时构造有向赋权图中不会含
%负权回路,所以不会出现k=n
dvt=Inf;t=n;%进入调整过程,dvt表示调整量
while
(1)%通过回溯计算调整量
if(a(s(t),t)>0)
dvtt=C(s(t),t)-f(s(t),t);%前向弧调整量
elseif(a(s(t),t)<0)
dvtt=f(t,s(t));
end%后向弧调整量
if(dvt>dvtt)
dvt=dvtt;
end
if(s(t)==1)
break;
end%当t的标号为vs时,终止计算调整量
t=s(t);
end%继续调整前一段弧上的流f
pd=0;
if(wf+dvt>=wf0)
dvt=wf0-wf;pd=1;
end%如果最大流量大于或等于预定的流量值
t=n;
while
(1)%调整过程
if(a(s(t),t)>0)
f(s(t),t)=f(s(t),t)+dvt;%前向弧调整
elseif(a(s(t),t)<0)
f(t,s(t))=f(t,s(t))-dvt;
end%后向弧调整
if(s(t)==1)
break;
end%当t的标号为vs时,终止调整过程
t=s(t);
end
if(pd)
break;
end%如果最大流量达到预定的流量值
wf=0;
for(j=1:
n)
wf=wf+f(1,j);
end
end%计算最大流量
zwf=0;
for(i=1:
n)
for(j=1:
n)
zwf=zwf+b(i,j)*f(i,j);
end
end
end%计算最小费用
f;%最小费用最大流
例求下图所示网络的最小费用最大流,弧旁
中的
分别表示顶点i到顶点j间弧的费用和容量。
b=[0106300;
004003;
0000124;
005020;
000005;
000000];
c=[0127800;
008005;
0000107;
009070;
000008;
000000];
[fwfzwf]=BGf(c,b)