Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CLIO_фокин24.doc
Скачиваний:
9
Добавлен:
18.11.2019
Размер:
3.11 Mб
Скачать

Описание алгоритма Прима:

Шаг 0: Инициализация (Если не 0, то пишем в таблицу, если =0, то не пишем)

  1. W(1) = O(1) = 1, W(i)=O(i)=0  i >1

  2.  i  S(1) : O(i)=1, D(i)=d(1,i)

Можно считать, что граф полный. Если ребра (i,j) нет, то d(i,j) = ∞. Или для всех вершин должны быть заданы списки S(i) номеров соседних с i вершин.

Основной шаг:

  1. k = argmin D(i), где iW -1(0)  O -1(>0) , т.е. W (i) = 0 & O (i)  0.

т.е. берем минимум по «видимым» вершинам. Если таких вершин нет, но пройдены не все вершины, то выход: граф не связен; если пройдены все вершины, то выход: кратчайшее остовное дерево (нормальное завершение)

  1. W(k)=1 – включить эту вершину

  2.  j  S(k) & Wj = 0 : O(j)=0 или D(j)>d(k,j)коррекция: O(j)=k и D(j)=d(k,j).

Число основных шагов должно быть равно n-1, если пройдем по всем вершинам.

Остовное дерево состоит из ребер (i,O(i)).

Трудоемкость алгоритма Прима: (волновой алгоритм)

И нициализация – линейное время

  1. – O(n)

  2. – O(1)

  3. – O(n)

О сновной шаг (повторяется (n-1) раз):

  1. – O(n)

  2. – O(1)

  3. – коррекция: O(n)

Трудоемкость = (n-1)O(n)=O(n2)

Корректность алгоритма Прима.

Каждый раз подключается новая вершина  строится связный граф без циклов и с n-1 ребром  алгоритм Прима строит дерево. Почему это МОД?

Утверждение: d(G0)=d(G1), где G0-дерево, построенное алгоритмом Прима, G1-МОД.

Д оказательство. Множества вершин в G0 = (V, E0) и G1 = (V, E1) совпадают. Пронумеруем вершины и ребра G0 в порядке их включения алгоритмом Прима.

У каждой вершины только один сосед в G0 с меньшим номером – «отец»!

Введем целочисленное расстояние

Пусть E0  E1. Выберем ребро e = (n1, n2)E0 \ E1  с минимальным номером. Пусть n1<n2. Ребра G1 не нумерованы. Пойдем по ним от вершины n1 к n2, пока впервые не встретим такое ребро l = (n3, n4), что n3<n2n4.

  1. n 2=n4l E0 , иначе n2 имеет в G0 двух соседей n1,n3 < n2.

  2. n2<n4  если l E0 , то номер ребра l больше номера ребра e.

В любом случае граф G2 = (V, E1 + e - l) является деревом и ρ (G0,G2) < ρ (G0,G1) (число ребер = n-1, при добавлении ребра e появился цикл, а при удалении реб­ра l из цикла связность не нарушится, min номер ребра в E0 \ E1 увеличивается).

Ребра e,l R (W) на шаге n2 и алгоритм Прима выбрал ребро ed(e) ≤ d(l)  d(G2) ≤ d(G1). Но G1 – МОД. Поэтому d(G2)=d(G1).  G2 – тоже МОД.

Повторим в цикле выбор ребер e и l и переход от Gk к Gk+1. На каждом шаге ρ (Gk,G1) убывает по крайней мере на 1 и не позже, чем через n-1 шаг будет =0, т.е. деревья G0 и Gk совпадут. Получили цепочку: d(Gk= G0) = … = d(G1).

Пример. На шаге n2=7 вершины n1=2 и n3=5 будут включены, а n2 и n4=9 нет.

Этап 1. Этап 2. Этап 3.

20. Алгоритм Тарьяна (для планарных графов МОД строится за O(n)).

NKS

BV

i

Соседи (SSV)

I

4

1

2 4 5

II

3

2

1 5 3

II

2

3

2 5 6

I

1,5

4

1 5 7

I

4

5

1 4 7 8 6 3 2

III

9

6

3 5 8 9 7

IV

8

7

6 8 5 4

IV

7

8

9 6 5 7

III

6

9

8 6

Макрографы тоже планарные

На каждом шаге число операций ≈ числу дуг=2R<6n

  1. Формируем списки SSV соседей всех вершин.

  2. Для всех вершин находим ближайшую вершину BV и строим симметричное замыкание BV: если BV(i)=j и BV(j) ≠ i, то в BV(j) добавляем i. В замыкании будет не более (n-1) неориен.ребра.

  3. П

    k = 0; NKS = 0;

    for (j = 1; j < n; j++) if NKS(j)=0 {

    Q = { j }; SKS(++k) = ;

    while (Q ≠  ) { i = pop( Q );

    NKS(i)=k; SKS(k)+=i;

    for all m  BV(i)

    if NKS(m) then Q+= m }}

    оиском сначала вширь по массиву BV выделяем компоненты связности.

NKS(j) – номер компоненты связности j-ой вершины,

SKS(k) –список вершин k-ой компоненты связности,

Q – текущая очередь при поиске k –компоненты,

pop(Q) – выбор первой вершины из очереди.

Списки вершин компонент связности на выходе:

I: 1,4,5 II: 2,3 III: 6,9 IV: 7,8

Трудоемкость этой части = числу ребер в симметрическом замыкании < 2n.

  1. Ч

    R.d = ∞; Q = ; kk=k;

    for (t = 1; t < kk; t++) {

    for all i  SKS(t)

    for all j SSV(i) {

    k=NKS(j);

    if R[k].d > d(i,j)

    then{ Q+= k;

    R[k]={d (i, j),i, j}}

    while (Q ≠ )

    R[pop(Q)].d= ∞; }

    ИСТКА. Формируем ребра макрографа в виде списков соседних компонент связ­ности, просматривая по списку SKS вершины текущей компоненты. Если в списке соседей очередной вершины i встретится вершина j из другой ком­поненты k с более коротким ребром между компо­нентами, то запишем в список соседних макровершин блок k/d (i, j), где d – длина кратчайшего ребра между вершинами компонент.

Список соседей до очистки

Список соседей после очистки

I

_ II _ ,

_ IV_ ,

_III_

I

_ II _ ,

_ IV_ ,

_III_

4(1,2)

3(4,7)

4(5,6)

4(1,2)

3(4,7)

4(5,6)

II

__I_ ,

_III_

II

__I_ ,

_III_

4(2,1)

3(3,6)

4(2,1)

3(3,6)

III

__II_ ,

__I_,

_IV_ ,

__IV_

III

__II_ ,

__I_ ,

_IV_

3(6,3)

4(6,5)

6(6,8)

4(6,7)

3(6,3)

4(6,5)

4(6,7)

IV

_III_,

__I__

__I__

IV

_III_,

__I__

4(7,6)

5(7,5)

3(7,4)

4(7,6)

3(7,4)



Этап 4. Все вершины одной компоненте  STOP.

Особенность реализации алгоритма: Заводим и обнуляем массив структур R из n компонент прямого доступа, которому соответствует на рисунке одна строка таблицы списков соседей. Когда в какую-либо структуру вносится информация, адрес структуры заносим в «журнал» Q. Для очистки массива R мы обнуляем поля, адреса которых есть в журнале. При этом очистка не требует большей работы, чем запись. Иначе только очистка может потребовать n2 операций.

Макрограф планарного графа – планарен, а трудоемкость удовлетворяет неравенству Tn<Cn+Tn/2,  линейна по n.