Thuật toán Kruskal tìm cây khung nhỏ nhất
2017-08-03Bài gốc
Đề bài
Cho đơn đồ thị vô hướng liên thông G = (V, E) gồm n đỉnh và m cạnh, các đỉnh được đánh số từ 1 tới n và các cạnh được đánh số từ 1 tới m, mỗi cạnh có trọng số không âm c. Hãy tìm cây khung nhỏ nhất của đồ thị G
Giới hạn:
- 1 ≤ n ≤ 10000
- 1 ≤ m ≤ 15000
- 0 ≤ c ≤ 10000
Định dạng test
Input:
- Dòng 1: Chứa hai số n, m.
- M dòng tiếp theo, dòng thứ i có dạng ba số nguyên u, v, c. Trong đó (u, v) là chỉ số hai đỉnh đầu mút của cạnh thứ i và c trọng số của cạnh đó.
Output:
- Gồm 1 dòng duy nhất: Ghi trọng số cây khung nhỏ nhất.
Ví dụ:
Thuật toán
Kruskal.
Source code
Ngôn ngữ: C++.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
const int N = 10000 + 5;
const int M = 15000 + 5;
int n, m, lab[N];
pair<ll, ii> e[M];
int root(int u) {
return (lab[u] < 0) ? u : lab[u] = root(lab[u]);
}
void merge(int u, int v) {
u = root(u);
v = root(v);
if (u == v) return;
if (lab[u] > lab[v]) swap(u, v);
lab[u] += lab[v];
lab[v] = u;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
// input
cin >> n >> m;
FOR(i,1,m)
cin >> e[i].se.fi >> e[i].se.se >> e[i].fi;
// dsu init
memset(lab, -1, sizeof lab);
// sort edges
sort(e+1, e+m+1);
// build mst
ll cost = 0; // minimum cost of mst
ll mste = 0; // edge number of mst
FOR(i,1,m) {
if (mste == n - 1) break;
int u = e[i].se.fi;
int v = e[i].se.se;
ll c = e[i].fi;
if (root(u) != root(v)) {
cost += c;
mste++;
merge(u, v);
}
}
// output
cout << cost;
return 0;
}
Độ phức tạp
Xấp xỉ O(MlogM + MlogN)