최소 스패닝 트리(MST)의 기본 연습문제입니다.
크루스칼 알고리즘과 프림 알고리즘 둘 다 사용하였습니다.
크루스칼 알고리즘은 가중치가 낮은 순으로 간선을 골라주시면 되는데 사이클 방지를 위해 Union-find를 이용합니다.
뽑은 간선의 두 정점을 union-find로 이어주고 parent를 같게합니다.
그 다음에 뽑은 간선의 두 정점의 parent가 같으면 사이클이 발생하므로 제외시켜주는 방식입니다.
프림 알고리즘은 한 정점을 임의로 정하여 bfs와 비슷한 방식으로 순회하는데
방문한 정점에 연결된 간선 모두를 우선순위 큐에 넣고
다음 방문할 정점은 큐에 있는 정점 중 가중치가 가장 낮은 정점입니다.
만약 이미 방문하여 연결된 간선 모두를 큐에 넣었던 정점이면 continue를 해주고 방문하지 않은 정점에 연결된 간선만 모두 추가합니다.
두 방식 모두 N - 1개의 간선을 골랐으면 break를 하고 지금까지 더했던 가중치를 출력해줍니다.
[Kruskal]
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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | #include <iostream> #include <vector> #include <algorithm> using namespace std; typedef struct Point { int u; int v; int w; }; vector<Point> list; int parent[10001]; int N, M, ans, cnt; bool cmp(Point a, Point b) { if (a.w < b.w) return true; else return false; } void init() { for (int i = 1; i <= N; i++) { parent[i] = i; } } int find(int v) { if (parent[v] == v) return v; return parent[v] = find(parent[v]); } void Union(int x, int y, int w) { int a = find(x); int b = find(y); if (a == b) return; parent[b] = a; ans += w; cnt++; } void func() { for (int i = 0; i < M; i++) { int u = list[i].u; int v = list[i].v; int w = list[i].w; Union(u, v, w); if (cnt == N - 1) break; } cout << ans << '\n'; } void input() { int u, v, w; cin >> N >> M; for (int i = 0; i < M; i++) { cin >> u >> v >> w; list.push_back({ u,v,w }); } sort(list.begin(), list.end(), cmp); } int main() { cin.tie(NULL); cout.tie(NULL); ios::sync_with_stdio(false); input(); init(); func(); return 0; } | cs |
[Prim]
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
57
58
|
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
vector<pair<int, int> > list[10001];
bool visit[10001];
int N, M, ans, cnt;
void func() {
priority_queue<pair<int, int> > q;
for (int i = 0; i < list[1].size(); i++) {
q.push({ -list[1][i].second, list[1][i].first });
}
visit[1] = true;
while (!q.empty()) {
int x = q.top().second;
int w = -q.top().first;
q.pop();
if (visit[x]) continue;
visit[x] = true;
ans += w;
cnt++;
if (cnt == N - 1) break;
for (int i = 0; i < list[x].size(); i++) {
int next = list[x][i].first;
int nextw = list[x][i].second;
q.push({ -nextw, next });
}
}
cout << ans << '\n';
}
void input() {
int u, v, w;
cin >> N >> M;
while(M--) {
cin >> u >> v >> w;
list[u].push_back({ v, w });
list[v].push_back({ u, w });
}
}
int main() {
cin.tie(NULL); cout.tie(NULL);
ios::sync_with_stdio(false);
input();
func();
return 0;
}
|
cs |
'algorithm > MST' 카테고리의 다른 글
boj 1647 도시 분할 계획 (0) | 2021.03.19 |
---|---|
boj 1922 네트워크 연결 (0) | 2021.03.19 |