Правильный способ сделать это — начать поиск в глубину с произвольного узла N, что можно сделать за линейное время. Каждый раз, когда вы сталкиваетесь с новым узлом, вы регистрируете путь, по которому вы до него добирались. Это даст вам кратчайший путь между N и каждым другим узлом в графе.
Чтобы найти кратчайший путь между узлами V и W, вы смотрите на путь от V до N и путь от N до W. Это даст вам кратчайший путь между V и W, за исключением, возможно, лишнего бита в середине, где вы нажмете N, а затем вернетесь назад. снова. Например, предположим, что путь от V до N таков:
V, A, B, C, D, E, N
а путь от N до W таков:
N, E, D, F, G, W
тогда вы можете видеть, что путь от V до W после их объединения приведет к D, а затем пойдет вверх к N через E и обратно. Это должно быть удалено из вашего пути, чтобы дать вам кратчайший путь. Другими словами, вы сканируете назад от конца первого пути и вперед по второму пути, пока не дойдете до последнего общего узла (в данном случае D), и вы отсекаете пути и соедините их вместе в этой точке, чтобы у вас осталось
V, A, B, C, D, F, G, W
Это даст вам кратчайший путь. Вы можете видеть это, потому что любой путь из V в W, который не повторяет никаких узлов, должен быть кратчайшим путем в связующем дереве.
Вот остовное дерево, взятое из Википедии в качестве примера. Если вы возьмете V как верхний левый, N как верхний правый и W как нижний левый, вы увидите, что кратчайший путь от V до W — это кратчайший путь от V до N, объединенный с кратчайшим путем от N em> в W, но без дублированного раздела в середине, где мы подходим к N и возвращаемся к основному пути.
![Пример связующего дерева](https://i.stack.imgur.com/iuUxZ.png)
person
chiastic-security
schedule
11.12.2014