Перейти до основного вмісту

Мінімальне кістякове дерево — алгоритм Крускала з системою неперетинних множин

Пояснення задачі про мінімальне кістякове дерево та алгоритму Крускала шукайте в головній статті про алгоритм Крускала.

У цій статті ми розглянемо структуру даних "Система неперетинних множин" для реалізації алгоритму Крускала, що дозволить алгоритму досягти часової складності O(MlogN)O(M \log N).

Опис

Так само, як і в простій версії алгоритму Крускала, ми сортуємо всі ребра графа в неспадному порядку ваг. Потім розміщуємо кожну вершину в її власному дереві (тобто в її множині) за допомогою викликів функції make_set — на це загалом піде O(N)O(N). Ми перебираємо всі ребра (у відсортованому порядку) і для кожного ребра визначаємо, чи належать його кінці до різних дерев (двома викликами find_set, кожен за O(1)O(1)). Нарешті, нам потрібно виконати об'єднання двох дерев (множин), для чого буде викликана функція СНМ union_sets — також за O(1)O(1). Отже, ми отримуємо загальну часову складність O(MlogN+N+M)O(M \log N + N + M) = O(MlogN)O(M \log N).

Реалізація

Ось реалізація алгоритму Крускала з об'єднанням за рангом.

vector<int> parent, rank;

void make_set(int v) {
parent[v] = v;
rank[v] = 0;
}

int find_set(int v) {
if (v == parent[v])
return v;
return parent[v] = find_set(parent[v]);
}

void union_sets(int a, int b) {
a = find_set(a);
b = find_set(b);
if (a != b) {
if (rank[a] < rank[b])
swap(a, b);
parent[b] = a;
if (rank[a] == rank[b])
rank[a]++;
}
}

struct Edge {
int u, v, weight;
bool operator<(Edge const& other) {
return weight < other.weight;
}
};

int n;
vector<Edge> edges;

int cost = 0;
vector<Edge> result;
parent.resize(n);
rank.resize(n);
for (int i = 0; i < n; i++)
make_set(i);

sort(edges.begin(), edges.end());

for (Edge e : edges) {
if (find_set(e.u) != find_set(e.v)) {
cost += e.weight;
result.push_back(e);
union_sets(e.u, e.v);
}
}

Зауважимо: оскільки мінімальне кістякове дерево міститиме рівно N1N-1 ребер, ми можемо зупинити цикл for, щойно знайдемо їх стільки.

Задачі для практики

Список задач для практики на цю тему дивіться в головній статті про алгоритм Крускала.

Відеоматеріали