C++ アルゴリズムとデータ構造のライブラリ
#include "library/graph/mst/kruskal.hpp"cost: 全域の総コスト。全域に達しない場合、INFedges: 全域に達するためのvector<Edge>
$O(ElogV)$
vector<Edge> edges;
MinSpanTree mst = kruskal(edges, V);
mst.cost;
mst.edges;
#pragma once
#include "library/graph/base/edge.hpp"
#include "library/various/union_find.hpp"
struct MinSpanTree {
long long cost;
vector<Edge> edges;
};
MinSpanTree kruskal(vector<Edge> edges, int v_cnt) {
sort(edges.begin(), edges.end(),
[](const Edge &a, const Edge &b) { return a.cost < b.cost; });
UnionFind uf(v_cnt);
long long total = 0ll;
vector<Edge> es;
for (auto &&e : edges) {
if (uf.unite(e.from, e.to)) {
es.emplace_back(e);
total += e.cost;
}
}
// 全域に達しない場合
if (uf[0] < v_cnt) {
total = INF;
}
return {total, es};
}#line 2 "library/graph/base/edge.hpp"
struct Edge {
int from, to;
long long cost;
int idx;
Edge(int from, int to, long long cost = 1, int idx = -1)
: from(from), to(to), cost(cost), idx(idx) {}
};
#line 2 "library/various/union_find.hpp"
struct UnionFind {
private:
vector<int> parent, size;
public:
UnionFind(int N) {
parent.assign(N, -1);
size.assign(N, 1);
}
int operator[](int p) { return size[find(p)]; }
int find(int p) { return !~parent[p] ? p : (parent[p] = find(parent[p])); }
bool unite(int a, int b) {
int x = find(a), y = find(b);
if (x == y) return false;
if (size[x] > size[y]) swap(x, y);
parent[x] = y, size[y] += size[x];
return true;
}
};
#line 4 "library/graph/mst/kruskal.hpp"
struct MinSpanTree {
long long cost;
vector<Edge> edges;
};
MinSpanTree kruskal(vector<Edge> edges, int v_cnt) {
sort(edges.begin(), edges.end(),
[](const Edge &a, const Edge &b) { return a.cost < b.cost; });
UnionFind uf(v_cnt);
long long total = 0ll;
vector<Edge> es;
for (auto &&e : edges) {
if (uf.unite(e.from, e.to)) {
es.emplace_back(e);
total += e.cost;
}
}
// 全域に達しない場合
if (uf[0] < v_cnt) {
total = INF;
}
return {total, es};
}