Вы можете использовать списки смежности, чтобы ускорить решение (но не для плотных графов), но даже тогда вы не получите O (V log V) без кучи Фибоначчи.
Возможно, алгоритм Крускала будет проще для вас понять. Он не имеет очереди приоритетов, вам нужно только один раз отсортировать массив ребер. В основном это выглядит так:
- Вставить все ребра в массив и отсортировать их по весу
- Переберите отсортированные ребра, и для каждого ребра, соединяющего узлы i и j, проверьте, соединены ли i и j. Если они есть, пропустите край, иначе добавьте край в MST.
Единственный улов - быстро определить, связаны ли два узла. Для этого вы используете структуру данных Union-Find, которая выглядит следующим образом:
int T[MAX_#_OF_NODES]
int getParent(int a)
{
if (T[a]==-1)return a;
return T[a]=getParent(T[a]);
}
void Unite(int a,int b)
{
if (rand()&1)
T[a]=b;
else
T[b]=a;
}
В начале, просто инициализируйте T для всех -1, а затем каждый раз, когда вы хотите узнать, связаны ли узлы A и B, просто сравните их родителей - если они одинаковые, они связаны (как это getParent(A)==getParent(B)
). Когда вы вставляете ребро в MST, обязательно обновите Union-Find с помощью Unite(getParent(A),getParent(B))
.
Анализ прост: вы сортируете ребра и перебираете, используя UF, который принимает O (1). Таким образом, O (E logE + E) равно O (E log E).
Вот и все; -)