{ Цикл ввода названий стран }
repeat
Write('Центр империи = '); Readln(C);
C:= UpCase(C);
if not (C in ['A'..'Z']) then break;
Start:= GetPtr(C); { указатель на центр империи }
if Assigned(Start) then begin { если такая страна существует, }
InitList; { устанавливаем начальные значения в полях узлов }
Expand(Start); { расширяем "империю" от центра Start }
end;
until false
end.
В главной программе организован цикл, принимающий от пользователя исходную страну, из которой строится империя. Программа завершается при вводе любого символа, отличного от латинской буквы. Запустив программу, я ввел символ «E» и увидел на экране вот что.
E -> F D
F -> G A
D -> C
G -> I H
A -> B
C ->
I ->
H ->
B –>
Эти строки напечатаны операторами трассировки в процедуре Expand. Согласно первой строке из узла «E» мы попадаем в узлы «F» и «D». Согласно второй – из узла «F» движемся в узлы «G» и «A», и так далее. Последние четыре строки показывают, что узлы «C», «I», «H» и «B» оказались на окраинах империи, и продвижений оттуда нет. По этой трассировке нетрудно нарисовать дерево воображаемого продвижения купцов (рис. 145).

Сопоставьте это дерево с тем, что нацарапал на песке придворный программист (рис. 144). Разницы не заметит только слепой. В чем дело? Неужели вкралась ошибка?
Но, прежде чем огорчаться, сравните расстояния между центром империи и другими узлами – на обоих рисунках они совпадают. А это значит, что можно найти разные варианты кратчайших путей. Какой из них выберет программа – дело случая. Точнее, это определяется порядком ввода узлов. Мы знаем, что порядок строк входного файла не влияет на форму графа, но он влияет на выбор одного из кратчайших путей между узлами. Правда, купцам до этого дела нет, – ведь расстояния по таким путям будут одинаковыми.
Теперь все готово для создания полной версии программы. Пройдясь по графу вширь, мы разместили в узлах необходимые данные: расстояния от корня и обратные ссылки на пройденные узлы. Пора ставить победную точку – напечатать кратчайший путь между двумя узлами и длину этого пути.
Для постройки кратчайшего пути надо указать узел, из которого мы хотим попасть в центр империи. Двигаясь из него по цепочке обратных ссылок в направлении центра, мы, в конце концов, попадем в него. Значение обратной ссылки в центре империи равно NIL, что будет признаком окончания пути. С этой работой справится несложная функция MakePath – «создать путь».
function MakePath(arg : PNode): string;
В функцию передается узел, от которого надо вернуться к корню дерева, то есть к центру империи. Результатом будет строка пути вида «A –> B –>