Порядок ввода
|
Порядок вывода
|
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]
Достарыңызбен бөлісу: |