图论相关问题.docx
《图论相关问题.docx》由会员分享,可在线阅读,更多相关《图论相关问题.docx(26页珍藏版)》请在冰豆网上搜索。
图论相关问题
图论相关问题
图论中的图是指表示具体事物的集合V和事物之间的关系集合E所组成的偶对。
集合V,集合E中的元素称为图的边。
注:
一般:
用
(也用n或p表示)和
(也用m或q表示)分别表示图G的顶点数和边数。
注:
无向图一般用G表示,有向图一般用D表示。
一、最短路问题(多阶段决策问题)
(1)相关概念
Df1通路:
在无向图G=(V,E)中,顶点与边的有限非空交替序列w=v0e1v1e2…ekvk称为一条从v0到vk的通路,记为:
其中:
ei的端点是vi-1,vi。
Df2道路:
边不重复的通路称为道路,记为。
Df3路径:
顶点不重复(边自然不重复)的通路称为路径,记为。
Df4链:
若途径的边均不相同,则称为链。
Df5圈:
起点和终点重合的路径称为圈。
Df6连通图:
任意两点间均有通路的图称为连通图。
Df7最短路:
在赋权图G中,从顶点u到顶点v的具有最小权的路P*(u,v),称为u到v的最短路。
(2)模型形式与背景
设备更新问题
选址问题
中心问题:
要求网络中最远的被服务点离服务设施的距离尽可能小。
重心问题:
要求设施到所有服务对象点的距离总和最小,一般要考虑人口密度问题,要使全体服务对象来往的平均路程最短。
线路的布设
运输安排
运输网络最小费用流
旅游线路中的最短路
(3)算法实现:
Dijkstra算法
设G为赋权有向图或无向图,G边上的权均非负,G为(p,q)图:
(1)令l(v0)=0(l(vi)表示从起点v0到vi的最短路长),当v≠v0,令:
l(vi)=∞,S0=v0,i=0;
(2)对每一个u∈Si,用min{l(u),l(vi)+l(vi,u)}代替l(u),算出min{l(u)|u∈Si},设vi+1是达到这个极小值的一个顶点,令Si+1=Si∪{vi+1};其中Si=V-Si表示Si的补集。
(3)如果i=p-1,则停止,如果i(2)(其中p为图的阶数)。
无向图最短路问题Lingo程序:
model:
sets:
!
优化建模lingo、lindo软件p290求出的最短路就是看x(i,j)的取值,1就是ij之间有连线,0就是i之间没连线;
cities/1..11/;
roads(cities,cities):
p,w,x;
endsets
data:
p=!
邻接矩阵;
w=!
带权邻接矩阵;
enddata
n=@size(cities);
min=@sum(roads:
w*x);
@for(cities(i)|i#ne#1#and#i#ne#n:
@sum(cities(j):
p(i,j)*x(i,j))=@sum(cities(j):
p(j,i)*x(j,i)));
@sum(cities(j):
p(1,j)*x(1,j))=1;
End
有向图最短路问题2Lingo程序(相对熟悉)
model:
sets:
cities/1..7/;
roads(cities,cities)/1,21,32,42,52,63,43,53,64,75,76,7/:
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;
end
有向图最短路问题1Lingo程序:
model:
sets:
nodes/1..6/;
arcs(nodes,nodes)|&1#lt#&2:
c,x;!
)|&1#lt#&2:
endsets
data:
c=7122131447122131712217127;
enddata
n=@size(nodes);
min=@sum(arcs:
c*x);
@for(nodes(i)|i#ne#1#and#i#ne#n:
@sum(arcs(i,j):
x(i,j))=@sum(arcs(j,i):
x(j,i)));
@sum(arcs(i,j)|i#eq#1:
x(i,j))=1;
end
Floyd算法
D(i,j):
i到j的距离;
R(i,j):
i到j的插入点。
输入带权邻接矩阵W(i,j),
(1)赋初值;对所有i,j:
d(i,j)←W(i,j),r(i,j)←j,k←1
(2)更新d(i,j),r(i,j):
对所有i,j,若:
d(i,k)+d(k,j)d(i,j)←d(i,k)+d(k,j),r(i,j)←k
(3)若k=p,停止;否则:
k←k+1,转
(2)。
floyd求最短路问题Matlab程序:
clear;clc;
n=23;a=zeros(n);
a(1,2)=8.6;a(2,3)=9.8;a(3,4)=8.1;a(4,5)=7.2;a(5,6)=11.8;a(6,17)=9.7;a(17,18)=8.3;a(18,19)=4.8;a(19,20)=8.2;a(20,21)=12.7;a(18,22)=9.2;a(22,23)=11.5;a(6,7)=7.3;a(7,8)=7.2;a(8,9)=8.0;a(8,10)=14.2;a(10,11)=6.8;a(8,12)=7.8;a(12,13)=5.6;a(13,14)=10.8;a(13,15)=12.2;
a(15,16)=10.2;%(带权邻接矩阵);
b=a+a';path=zeros(n);
fori=1:
n
path(:
i)=i;
end
fori=1:
n
forj=1:
n
ifb(i,j)==0&i~=j
b(i,j)=inf;
end
end
end
fork=1:
n
fori=1:
n
forj=1:
n
ifb(i,j)>b(i,k)+b(k,j)
b(i,j)=b(i,k)+b(k,j);
path(i,j)=k;
end
end
end
end
b,path
Floyd—warshall算法
二、最小生成树问题
(1)相关概念
Df树:
连通无圈图称为树。
(2)模型形式与背景
最短路问题:
设有一个铁路系统连接着若干个城市,x1是该系统中的一个固定城市,在该系统中试求从x1到其他各城市的最短路线。
(该问题可转化为在G=(V,E)的赋权图中找根x1在且权和最小的支撑树。
更一般地,设是有正值加权简单有向图,x1是G中的一个固定顶点,寻找根x1在的支撑外向树。
)
最小连接问题:
假设在某地区内要修建一个连接若干个城镇的公路系统,已知
与
之间直通公路的造价为
,试设计一个造价最低的建造方案。
城市供水、供电、供气系统中所有阀门或供电系统中的开关作为模拟图的顶点,而把供水、气管道或供电线路作为模拟图的边。
使得管道或电缆的长度之和最小,即费用最小。
(3)算法实现
Kruskal算法:
设G为由m个节点组成的联通赋权图。
(1)先把G中所有边按权数大小由小到大重新排列,并取权数最小的一边取为T中的边。
(2)从剩下的边中按
(1)中排列取下一条边,若该边与以前已取进T中的边形成某个回路,则舍去该边;否则也把该边也取进T中。
最小生成树Lingo程序:
model:
sets:
cities/1..10/:
level;!
优化建模lindo、lingo软件p300利用Kruskal算法求解;
link(cities,cities):
distance,x;
endsets
data:
distance=!
带权邻接矩阵;
enddata
n=@size(cities);
min=@sum(link(i,j)|i#ne#j:
distance(i,j)*x(i,j));
@sum(cities(i)|i#gt#1:
x(1,i))>=1;
@for(cities(i)|i#gt#1:
@sum(cities(j)|j#ne#i:
x(j,i))=1;
@for(cities(j)|j#gt#1#and#j#ne#i:
level(j)>=level(i)+x(i,j)-(n-2)*(1-x(i,j))+(n-3)*x(j,i);
);
@bnd(1,level(i),999999);
level(i)<=n-1-(n-2)*x(1,i););
@for(link:
@bin(x));
End
最小生成树Matlab程序:
function[Wt,Pp]=mintreek(n,W)
%图论中最小生成树Kruskal算法及画图程序M-函数
%格式[Wt,Pp]=mintreek(n,W):
n为图顶点数,W为图的带权邻接矩
%阵,不构成边的两顶点之间的权用inf表示。
显示最小生成树的边及
%顶点,Wt为最小生成树的权,Pp(:
1:
2)为最小生成树边的两顶点,
%Pp(:
3)为最小生成树的边权,Pp(:
4)为最小生成树边的序号;
%附图,红色连线为最小生成树的图;
%例如
%n=6;w=inf*ones(6);
%w(1,[2,3,4])=[6,1,5];w(2,[3,5])=[5,3];
%w(3,[4,5,6])=[5,6,4];w(4,6)=2;w(5,6)=6;
%[a,b]=mintreek(n,w)
%ByX.D.DingJune2000
tmpa=find(W~=inf);[tmpb,tmpc]=find(W~=inf);
w=W(tmpa);e=[tmpb,tmpc];%w是W中非inf元素按列构成的向量
%e的每一行元素表示一条边的两个顶点的序号
[wa,wb]=sort(w);E=[e(wb,:
),wa,wb];[nE,mE]=size(E);
temp=find(E(:
1)-E(:
2));E=E(temp,:
);
P=E(1,:
);k=length(E(:
1));
while(rank(E)>0)
temp1=max(E(1,2),E(1,1));temp2=min(E(1,2),E(1,1));
fori=1:
k;
if(E(i,1)==temp1),E(i,1)=temp2;end;
if(E(i,2)==temp1),E(i,2)=temp2;end;
end;
a=find(E(:
1)-E(:
2));E=E(a,:
);
if(rank(E)>0),P=[P;E(1,:
)];k=length(E(:
1));end;
end;
Wt=sum(P(:
3));Pp=[e(P(:
4),:
),P(:
3:
4)];
fori=1:
length(P(:
3));%显示顶点vi与边ej
disp(['','e',num2str(P(i,4)),'','(v',...
num2str(P(i,1)),'','v',num2str(P(i,2)),')']);
end;
%以下是画图程序
axisequal;holdon
[x,y]=cylinder(1,n);xm=min(x(1,:
));ym=min(y(1,:
));
xx=max(x(1,:
));yy=max(y(1,:
));
axis([xm-abs(xm)*0.15,xx+abs(xx)*0.15,ym-abs(ym)*0.15,yy+abs(yy)*0.15]);plot(x(1,:
),y(1,:
),'ko')
fori=1:
n;temp=['v',int2str(i)];
text(x(1,i),y(1,i),temp);end;
fori=1:
nE;plot(x(1,e(i,:
)),y(1,e(i,:
)),'b');end;
fori=1:
length(P(:
4));
plot(x(1,Pp(i,1:
2)),y(1,Pp(i,1:
2)),'r');end;
text(-0.35,-1.2,['最小生成树的权为','',num2str(Wt)]);
title('红色连线为最小生成树');axis('off');holdoff
Prim算法:
(1)先在G中任取一个节点
,并取进T中;
(2)令S=E(G)\E(T),其中E(G),E(T)分别为G与T的节点集;
(3)在所有连接E(T)的节点与S的节点的边中,选取权数最小的边(
),即
(4)将边(
)取入T中。
(5)重复步骤
(2)~(4),直至G中的节点都取入T中为止。
最小生成树的Matlab程序:
clc;clear;
M=1000;
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;zeros(2,7)];
a=a+a';a(find(a==0))=M;
result=[];p=1;tb=2:
length(a);
whilelength(result)~=length(a)-1
temp=a(p,tb);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))=[];
end
result%result的第一、二、三行分别表示生成树边的起点、终点、权。
三、匹配问题
(1)相关概念
Df1匹配:
设图G=(V,E),M是E的子集,若M的边互不相邻,则称M是G的一个匹配。
M的边称为匹配边,E\M的边称为自由边。
注:
若(u,v)∈M,则称u(或v)是v(或u)的配偶.若顶点v与M的一条边关联,则称v是M-饱和的;否则称为是M-非饱和的.
设M是G的一个匹配,若G的每个顶点都是M-饱和的,则称M是G的完美匹配。
设M是G的一个匹配,若不存在匹配M,使得:
|M|>|M|.则称M为G的最大匹配。
最大匹配不一定是完美匹配,完美匹配一定是最大匹配。
(2)模型形式与背景
工作安排问题:
情形一:
n个工人:
x1,x2,…,xn;n件工作:
y1,y2,…,yn,已知工人xi能胜任ki件工作(i=1,2,…,n),问能否存在一种安排使每人能分配到他能胜任的一件工作,若能,如何安排?
情形二:
假设有:
n个工人:
x1,x2,…,xn;n件工作:
y1,y2,…,yn,若工人xi担任工作yj的效率为wij(i,j=1,2,…,n),对每人分配一件工作,使得总效率最大。
(3)算法实现
匈牙利(Hungarian)算法:
求二元图的最大匹配。
匈牙利算法求最大匹配的Matlab程序:
m=5;n=5;A=[01100%匈牙利算法的MATLAB程序代码如下:
11011
01100
01100
00011];
M(m,n)=0;
for(i=1:
m)for(j=1:
n)if(A(i,j))M(i,j)=1;break;end;end%求初始匹配M
if(M(i,j))break;end;end%获得仅含一条边的初始匹配M
while
(1)
for(i=1:
m)x(i)=0;end%将记录X中点的标号和标记*
for(i=1:
n)y(i)=0;end%将记录Y中点的标号和标记*
for(i=1:
m)pd=1;%寻找X中M的所有非饱和点
for(j=1:
n)if(M(i,j))pd=0;end;end
if(pd)x(i)=-n-1;end;end%将X中M的所有非饱和点都给以标号0和标记*,程序中用n+1表示0标号,标号为负数时表示标记*
pd=0;
while
(1)xi=0;
for(i=1:
m)if(x(i)<0)xi=i;break;end;end%假如X中存在一个既有标号又有标记*的点,则任取X中一个既有标号又有标记*的点xi
if(xi==0)pd=1;break;end%假如X中所有有标号的点都已去掉了标记*,算法终止
x(xi)=x(xi)*(-1);%去掉xi的标记*
k=1;
for(j=1:
n)if(A(xi,j)&y(j)==0)y(j)=xi;yy(k)=j;k=k+1;end;end%对与xi邻接且尚未给标号的yj都给以标号i
if(k>1)k=k-1;
for(j=1:
k)pdd=1;
for(i=1:
m)if(M(i,yy(j)))x(i)=-yy(j);pdd=0;break;end;end%将yj在M中与之邻接的点xk(即xkyj∈M),给以标号j和标记*
if(pdd)break;end;end
if(pdd)k=1;j=yy(j);%yj不是M的饱和点
while
(1)P(k,2)=j;P(k,1)=y(j);j=abs(x(y(j)));%任取M的一个非饱和点yj,逆向返回
if(j==n+1)break;end%找到X中标号为0的点时结束,获得M-增广路P
k=k+1;end
for(i=1:
k)if(M(P(i,1),P(i,2)))M(P(i,1),P(i,2))=0;%将匹配M在增广路P中出现的边去掉
elseM(P(i,1),P(i,2))=1;end;end%将增广路P中没有在匹配M中出现的边加入到匹配M中
break;end;end;end
if(pd)break;end;end%假如X中所有有标号的点都已去掉了标记*,算法终止
M%显示最大匹配M,程序结束
Kuhn-Munkres可行顶点标号法:
求赋权完备二元图的最佳匹配。
求完美匹配Matlab程序:
n=4;A=[4551
2246
4233
5021];
for(i=1:
n)L(i,1)=0;L(i,2)=0;end
for(i=1:
n)for(j=1:
n)if(L(i,1)M(i,j)=0;end;end
for(i=1:
n)for(j=1:
n)%生成子图Gl
if(L(i,1)+L(j,2)==A(i,j))Gl(i,j)=1;
elseGl(i,j)=0;end;end;end
ii=0;jj=0;
for(i=1:
n)for(j=1:
n)if(Gl(i,j))ii=i;jj=j;break;end;end
if(ii)break;end;end%获得仅含Gl的一条边的初始匹配M
M(ii,jj)=1;
for(i=1:
n)S(i)=0;T(i)=0;NlS(i)=0;end
while
(1)
for(i=1:
n)k=1;%否则.
for(j=1:
n)if(M(i,j))k=0;break;end;end
if(k)break;end;end
if(k==0)break;end%获得最佳匹配M,算法终止
S
(1)=i;jss=1;jst=0;%S={xi},T=?
while
(1)
jsn=0;
for(i=1:
jss)for(j=1:
n)if(Gl(S(i),j))jsn=jsn+1;NlS(jsn)=j;%NL(S)={v|u∈S,uv∈EL}
for(k=1:
jsn-1)if(NlS(k)==j)jsn=jsn-1;end;end;end;end;end
if(jsn==jst)pd=1;%判断NL(S)=T?
for(j=1:
jsn)if(NlS(j)~=T(j))pd=0;break;end;end;end
if(jsn==jst&pd)al=Inf;%如果NL(S)=T,计算al,Inf为∞
for(i=1:
jss)for(j=1:
n)pd=1;
for(k=1:
jst)if(T(k)==j)pd=0;break;end;end
if(pd&al>L(S(i),1)+L(j,2)-A(S(i),j))al=L(S(i),1)+L(j,2)-A(S(i),j);end;end;end
for(i=1:
jss)L(S(i),1)=L(S(i),1)-al;end%调整可行点标记
for(j=1:
jst)L(T(j),2)=L(T(j),2)+al;end%调整可行点标记
for(i=1:
n)for(j=1:
n)%生成子图GL
if(L(i,1)+L(j,2)==A(i,j))Gl(i,j)=1;
elseGl(i,j)=0;end
M(i,j)=0;k=0;end;end
ii=0;jj=0;
for(i=1:
n)for(j=1:
n)if(Gl(i,j))ii=i;jj=j;break;end;end
if(ii)break;end;end%获得仅含Gl的一条边的初始匹配M
M(ii,jj)=1;break
else%NL(S)≠T
for(j=1:
jsn)pd=1;%取y∈NL(S)\T
for(k=1:
jst)if(T(k)==NlS(j))pd=0;break;end;end
if(pd)jj=j;break;end;end
pd=0;%判断y是否为M的饱和点
for(i=1:
n)if(M(i,NlS(jj)))pd=1;ii=i;break;end;end
if(pd)jss=jss+1;S(jss)=ii;jst=jst+1;T(jst)=NlS(jj);%S=S∪{x},T=T∪{y}
else%获得Gl的一条M-增广路,调整匹配M
for(k=1:
jst)M(S(k),T(k))=1;M(S(k+1),T(k))=0;end
if(jst==0)k=0;end
M(S(k+1),NlS(jj))=1;break;end;end;end;end
MaxZjpp=0;
for(i=1:
n)for(j=1:
n)if(M(i,j))MaxZjpp=MaxZjpp+A(i,j);end;end;end
M%显示最佳匹配M
MaxZjpp%显示最佳匹配M的权,程序结束。
四、覆盖问题
(1)相关概念
Df1覆盖:
设G=(V,E),K是V的子集合,若G的每一条边都与K的一个顶点关联,则称K是图G的一个覆盖。
设K是G的一个覆盖,若不存在覆盖K,使得:
|K|<|K|,则称K是一个最小覆盖。
Df2控制集:
设G是连通图,DV(G),对每个v∈V(G),或者v在D中,或者v与D中某个顶点相邻,即D∩N(v)≠,则称D为G的一个控制集.若D是控制集,而D的任何真子集都不是控制集,则称D是极小控制集。
顶点数最少的控制集称为最小控制集。
最小控制集所含顶点数目称为控制数。