Сначала сгенерируйте MST. Теперь, если вы добавите свободный край, вы создадите ровно один цикл. Затем вы можете удалить самое тяжелое ребро в цикле, чтобы получить более дешевое дерево.
Чтобы найти лучшее дерево, которое вы можете сделать, добавив одно свободное ребро, вам нужно найти самое тяжелое ребро в MST, которое вы можете заменить со свободным.
Вы можете сделать это, проверяя по одному свободному ребру за раз:
- Выберите свободный край
- Найдите наименьшего общего предка в дерево (из произвольного root) смежных с ним вершин
- Запомните самое тяжелое ребро на пути между вершинами свободного ребра
Когда вы закончите, вы знаете, какие свободные Используемый край - это тот, который связан с самым тяжелым краем дерева, и вы знаете, какой край он заменяет.
Чтобы ускорить шаги (2) и (3), вы можете запомнить глубину каждого узел и подключить его к нескольким предкам, как пропустить список. Затем вы можете выполнить эти шаги за O (log | V |), что приведет к общей сложности O ((| E | + k) log | V |), что довольно неплохо.
РЕДАКТИРОВАТЬ: еще более простой способ
Подумав немного, кажется, есть супер простой способ выяснить, какой свободный край использовать и какой край MST заменить.
Независимо от k возможных свободных ребер, вы строите MST из других ребер, используя алгоритм Крускала, но модифицируете обычную структуру данных несвязанных множеств следующим образом:
- Используйте объединение по размеру или ранг, но не сжатие пути. Затем каждая операция объединения устанавливает sh ровно одну ссылку и занимает O (log N) времени, а длина всех путей будет не более O (log N).
- Для каждой ссылки запомните индекс ребра, вызвавшего его создание.
Затем для каждого возможного свободного ребра вы можете пройти вверх по ссылкам в структуре непересекающихся множеств, чтобы точно определить, в какой точке его конечные точки были соединены с тот же связанный компонент. Вы получите индекс последнего необходимого ребра, т. Е. Тот, который он заменит, и свободный край с наибольшим целевым индексом замены - это тот, который вы должны использовать.