Каранаев Линар Минтимерович Стерлибашево 2017 содержание глава реферативное изложение



бет30/64
Дата02.01.2022
өлшемі1.78 Mb.
#452913
түріИзложение
1   ...   26   27   28   29   30   31   32   33   ...   64
обб русский

Порядок ввода

Порядок вывода

N

X1 Y1


X2Y2

:

XnYn



X.xx

где X.xx – минимальная общая длина веревки с точностью до двух знаков в дробной части.



Порядок ввода

Порядок вывода

5

100 200

200 200

300 400

400 200

400 100


623.61

Ограничения:

0≤N≤100


-32 000≤Xi, Yi≤32 000

Рассмотрим домики тимуровцев как вершины графа, веревки между ними– как ребра графа, а длины веревок– как веса ребер. Теперь перед нами задача о минимальном остовном дереве. Тело программы, решающей эту задачу, может выглядеть следующим образом:

begin

InputData; {Ввод исходных данных}



MinTree: {Построение минимального остовного дерева}

OutputData: {Вывод результата}

end.

В данном случае исходный граф – полный, то есть существует ребро между любыми его двумя вершинами, поскольку по условиям задачи веревки можно протянуть между любыми двумя домиками.



В данной задаче удобно представлять граф в виде матрицы весов ребер: D[i,j] – расстояние между вершинами iи j. Ввод данных, обеспечивающий вычислениеD[i,j] по исходным данным задачи, представлен ниже и не требует комментариев.

procedure InputData;

begin

assign (mput,'input.txt');



reset(input);

readln(N);

for i:=l to N do readln(x[i],y[i]);

close(input);

for i:=l to N do

for j:=l to N do

D[1.j]:=sqrt(sqr(x[i]-x[j])*sqr(y[1]-y[j]));

end;


Результат работы алгоритма построения остовного дерева методом Прима будет представлен в виде массива Pred [l..N]: Pred [i] = j, то есть предком вершины i в остовном графе будет вершинаj, или, другими словами, минимальное остовное дерево будет содержать ребро (i, j). У вершины 1 предка не будет (Pred[l] = 0).

Ответ задачи по построенному остовному дереву получается следующим образом:

procedure OutputData:

var


Answer : single;

begin


Answer:=0;

for i:=2 to N do

Answer:=Answer+D[i, Pred[i]];

assign (output,'output.txt');

rewrite(output);

writeln(Answer:0:2);

close(output);

end;


Рассмотрим теперь собственно алгоритм Прима для построения минимального остовного дерева. Идея алгоритма Прима заключается в следующем: пусть А – это множество ребер части остова, растущей от пустого множества ребер к минимальному остовному дереву. Формирование множества A может начинаться с произвольной вершины, называемой корневой. Для определенности в реализации в качестве корневой выбирается вершина 1.

На каждом шаге в множество (дерево) А добавляется ребро наименьшего веса среди ребер, соединяющих вершины из дерева А с вершинами не из дерева А. После выполнения N - 1 раз таких добавлений мы получаем минимальное остовное дерево.

Для эффективной организации выбора нужного для добавления ребра используется очередь с приоритетами, в которой хранятся все вершины, еще не попавшие в дерево A. При этом каждая вершина i снабжена также приоритетом – специальной характеристикой Key[i], которая равна минимальному весу ребер, соединяющих вершину i с вершинами из А.

Более формально алгоритм Прима может быть записан следующим образом:

Ставим в очередь Q все вершины исходного графа

Устанавливаем для всех вершин Key[i] - бесконечность (MaxD)

Заносим в дерево А вершину 1:

key[l] = 0 – расстояние от нее до вершин дерева А

Pred[l] = 0 – у корневой вершины нет предка

Пока очередь Q не пуста

Выбираем из очереди вершину U такую, для которой расстояние

от нее до вершин из множества А минимально

Для каждой вершины V, соседней с U

(то есть в графе имеется ребро (U,V)).

если V находится в очереди и D[U,V]

то Pred[V]=U key[V]=D[U,V]

Ниже приведена реализация алгоритма Прима:

procedure MinTree;

Const

MaxD =le16; {бесконечность}



Free =0;

Used =1;

var

Lbl: array [l..MaxN] of byte;



Key: array [l..MaxN] of single;

U, v: byte;

Min: single;

begin


for i:=1 to N do

begin


key[i]:=MaxD;

Lbl[i]:=Free; { Всевершинывочереди}

end;

Key[l]:=0; { Начнем построение с остова с 1-й вершины}



Pred[l]:=0; { У 1-й вершины нет предка}

for i:=l to N do { Длявсехвершин }

begin

Min:=MaxD;



for j:=l to N do { Находимвершину}

if (Lbl[j]=Free) and (Key[j]

then begin u:=j; Min:=Key[j]; end;

Lbl[u]:=Used; { Помечаем ее как использованную}

forv:=ltoNdo { Для всех оставшихся в очереди вершин}

if (Lbl[v]=Free) and (D[u,v]

then

begin { Пересчитываем }



Key[v]:=D[u,v]; { расстояние до растущего остова }

Pred[v]:=u; { Переустанавливаем предка}

end;

end;


end; [2: 47-50]



Достарыңызбен бөлісу:
1   ...   26   27   28   29   30   31   32   33   ...   64




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет