Графы-1

advertisement
Представление графов и отношений
Граф G = (V,R), V – множество вершин, R – множество ребер
1) неориентированные графы
2) ориентированные, или орграфы,
3) взвешенные неориентированные графы
4) взвешенные ориентированные графы
5) мультиграфы
1
3
2
4
5
6
7
(1,2)
(3,1)
(2,3)
(4,3)
(5,6)
1 2 3 4 5 6 7
1
1 1
1
2 1
3 1 1
1
4
1
1
5
6
1
7
2
1
1
3
6
5
3
3
2
4
Формирование списков, задающих граф
Вершины графа – номера от 1 до n. Число ребер - m.
Ребро графа – два номера вершин (p,q).
i-е ребро – (v1[i],v2[i]).
________________________________________
for k:=1 to n do S[k]:=nil;
{обнуление указателей}
for i:=1 to m do
{формирование списков}
begin new(ps); ps^.s:=v2[i];
k:=v1[i]; ps^.p:=S[k]; S[k]:=ps;
{формирование 2-го элемента для неор.графа:}
new(ps); ps^.s:=v1[i];
k:=v2[i]; ps^.p:=S[k]; S[k]:=ps
end;
Представление графа массивом
смежных вершин
1
3
2
4
5
6
7
1 2 3 4 5 6 7 8 9 10
L
S D 2 3 1 3 1 2 4 3 6 5
2
2
3
1
1
1
0
1
3
5
8
9
10
11
Формирование массивов D, S и L для задания
неориентированного графа
for j:=1 to n do L[j]:=0;{обнуление длин списков}
for i:=1 to m do begin
{вычисление длин списков}
k:=v1[i]; L[k]:=L[k]+1;
k:=v2[i]; L[k]:=L[k]+1;
end;
S[1]:=1; {вычисление указателей на начала списков в
массиве D}
for j:=2 to n do S[j]:=S[j-1]+L[j-1];
for j:=1 to n do {дублирование указателей}
U[j]:=S[j];
for i:=1 to m do {распределение смежных вершин}
begin
{по спискам массива D}
k:=v1[i]; D[U[k]]:=v2[i]; U[k]:=U[k]+1
k:=v2[i]; D[U[k]]:=v1[i]; U[k]:=U[k]+1
end;
Просмотр неориентированного графа вглубь
Массив R для нумерации вершин графа по порядку просмотра.
Если i–я вершина при просмотре была j–й, то R[i]=j.
______________________________________________________________________
procedure deеp(k:integer);
var i: integer;
begin
for i:=1 to n do
if (M[k,i]=1)and(R[i]=0) then begin
nom:=nom+1; R[i]:=nom; deеp(i)
end
end;
______________________________________________________________________
for i:=1 to n do
R[1]:=1; nom:=1;
deеp(k);
R[i]:=0;
Выделение компонент связности графа
for i:=1 to n do C[i]:=0;
1
q:=0;
L S D 2
for i:=1 to n do
2
1
if C[i]=0 then begin
2
3
3
5
q:=q+1; C[i]:=q;
1
8
cdeеp(i)
1
9
end;
1
10
0
11
________________________
procedure cdeеp(k:integer);
var i: integer;
begin
for i:=S[k] to S[k]+L[k]-1 do
begin j:=D[i];
if C[j]=0 then
begin C[j]:=q; cdeеp(j) end
end
end;
2 3 4 5 6 7 8 9 10
3 1 3 1 2 4 3 6 5
Просмотр неориентированного графа вширь
V - уровни просмотренных вершин
P – номера просмотренных вершин (очередь)
__________________________________________
P[1]:=1; r:=1; t:=1; {очередь из одной вершины}
for i:=1 to n do V[i]:=0;
V[1]:=1;
{уровень для первой вершины}
while t<=r do
begin k:=P[t]; q:=V[k]+1;
for i:=S[k] to S[k]+L[k]-1 do
begin j:=D[i];
if V[j]=0 then begin
V[j]:=q; r:=r+1; P[r]:=j
end
end;
t:=t+1
end;
Поиск кратчайшего пути в лабиринте
Н
#
#
#
#
#
#
#
#
#
#
К
#
#
#
#
#
1
#
#
2
#
#
#
3
4
5
#
4
5
#
5
#
#
#
#
#
#
#
#
#
11
#
#
9
10
#
6
7
8
9
#
#
#
8
#
10
#
6
#
10
9
10
11
#
#
#
#
#
#
#
#
Pi[1]:=i0; Pj[1]:=j0; r:=1; t:=1;
L[i0,j0]:=1;
while t<=r do
begin i:=Pi[t]; j:=Pj[t]; q:=L[i,j]+1;
if L[i-1,j]=0 then begin
L[i-1,j]:=q; r:=r+1; Pi[r]:=i-1; Pj[r]:=j
end;
if L[i,j-1]=0 then begin
L[i,j-1]:=q; r:=r+1; Pi[r]:=i; Pj[r]:=j-1
end;
if L[i+1,j]=0 then begin
L[i+1,j]:=q; r:=r+1; Pi[r]:=i+1; Pj[r]:=j
end;
if L[i,j+1]=0 then begin
L[i,j+1]:=q; r:=r+1; Pi[r]:=i; Pj[r]:=j+1
end;
t:=t+1
end;
Отслеживание кратчайшего пути
k:=L[ik,jk]; i:=ik; j:=jk;
while k>0 do
begin Mi[k]:=i; Mj[k]:=j;
if L[i-1,j]<L[i,j] then i:=i-1
else if L[i,j-1]<L[i,j] then j:=j-1
else if L[i+1,j]<L[i,j] then i:=i+1
else j:=j+1;
k:=k-1
end;
Поиск кратчайшего пути в лабиринте
алгоритмом бэктрекинга
procedure Lab(i,j,k:integer);
begin
if (i=ik)and(j=jk) then
begin kmin:=k; {ЗАПОМНИТЬ МАРШРУТ} end
else if k<kmin then begin
if L[i-1,j]=0 then begin
L[i-1,j]:=1; Pi[k]:=i-1; Pj[k]:=j;
Lab(i-1,j,k+1);
L[i-1,j]:=0
end;
if L[i,j-1]=0 then begin . . . end;
if L[i+1,j]=0 then begin . . . end;
if L[i,j+1]=0 then begin . . . End
end
end;
Вызов процедуры поиска кратчайшего
пути в лабиринте
kmin:={∞};
L[i0,j0]:=1;
Pi[1]:=i0; Pj[1]:=j0;
Lab(i0,j0,2);
Эйлеров цикл
Вставка побочного цикла в основной цикл:
1
pb
i
k
i1
i
i
k
p
1
pb
1
1
p
количество ребер, входящих во все вершины:
for i:=1 to n do R[i]:=0;
for i:=1 to n do
for k:=S[i] to S[i]+L[i]-1 do
begin j:=D[k]; R[j]:=R[j]+1 end
Вычисление эйлерова цикла в орграфе
new(p); pb:=p; p^.s:=1; p^.p:=nil;
while p<>nil do
begin
if L[p^.s]>0 then begin
p1:=p^.p; i0:=p^.s; i:=0; p0:=p;
while i<>i0 do
begin new(p2); p^.p:=p2; i:=p^.s;
i1:=D[S[i]]; S[i]:=S[i]+1; L[i]:=L[i]-1;
i:=i1; p2^.s:=i; p:=p2
end;
p^.p:=p1; p:=p0
end
else p:=p^.p
end;
Вычисление эйлерова пути в орграфе
1. Вычисление количества ребер, входящих в
вершины.
2. Нахождение вершины ib – начала пути, и
вершины ik – конца пути.
3. Построение какого-либо пути из вершины ib в
вершину ik. После этого во всех вершинах
останется по одинаковому числу исходящих и
входящих дуг.
4. Построение полного пути добавлением
боковых циклов.
Вычисление начального пути в орграфе
new(p); pb:=p; p^.s:=ib; i:=ib;
while L[i]>0 do
begin
new(p1); p^.p:=p1;
i1:=D[S[i]]; S[i]:=S[i]+1;
L[i]:=L[i]-1;
p1^.s:=i1;
p:=p1; i:=i1
end;
p^.p:=nil;
Вычисление гамильтонова цикла в графе
procedure hamilton(k:integer);
var i,j:integer;
begin i:=P[k-1];
for j:=1 to n do
if (R[j]=0)and(M[i,j]=1) then begin
P[k]:=j; R[j]:=1;
if k=n then begin
if M[j,1]=1 then ВЫВОД
end
else hamilton(k+1);
R[j]:=0
end
end;
Вычисление топологической сортировки
Количество ребер, входящих во все вершины:
for i:=1 to n do R[i]:=0;
for i:=1 to n do
for k:=S[i] to S[i]+L[i]-1 do
begin j:=D[k]; R[j]:=R[j]+1 end
ИЛИ:
for i:=1 to n do R[i]:=0;
for k:=1 to m do
begin j:=D[k]; R[j]:=R[j]+1 end
Вычисление топологической сортировки
Массив P – очередь вершин, в которые нет
входящих дуг:
k:=0; t:=1;
for i:=1 to n do
if R[i]=0 then begin
k:=k+1; P[k]:=i
end;
Вычисление топологической сортировки
while t<=k do
begin i:=P[t];
for j:=S[i] to S[i]+L[i]-1 do
begin q:=D[j]; R[q]:= R[q]-1;
if R[q]=0 then begin
k:=k+1; P[k]:=q
end
end;
t:=t+1
end;
Вычисление обратной перестановки:
for i:=1 to n do
Q[P[i]]:=i;
Download