Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 시뮬레이션
- 16985
- mongodb
- dfs
- Naver Cloud
- gorilla/mux
- 점수 따먹기
- 17503
- BOJ
- 민준이와 마산 그리고 건우
- 맥주 축제
- 크루스칼
- SWEA
- NCP
- 구간합
- 다익스트라
- 21921
- c++
- 백준
- redis
- 정렬
- 이분 탐색
- 구현
- mst
- 누적합
- DP
- 11659
- 세그먼트 트리
- 최소신장트리
- golang
Archives
- Today
- Total
Gi-Log
백준(BOJ) 14621 나만 안되는 연애 C++ 풀이 본문
문제 링크: https://www.acmicpc.net/problem/14621
문제 풀이에 이용된 알고리즘: 크루스칼 알고리즘
주어진 그래프에서, 노드들을 연결하는 최단 거리 트리를 생성하는 문제이다. 즉, 최소 신장 트리 문제이며 크루스칼 알고리즘으로 간단히 풀 수 있다.
단, 간선을 입력 받을 때 "남초<->남초" 혹은 "여초<->여초"를 연결하는 간선은 애초에 크루스칼 알고리즘의 대상이 되는 간선 그룹에 포함시키지 않는다는 점이 중요하다.
최초 모든 대학을 연결하는 경로가 있다라는 조건이 있지 않고, 모든 대학을 연결하는 경로를 찾지 못하는 경우 -1을 출력하라고 했기 때문에, 크루스칼 알고리즘이 끝났을 때 바로 신장 트리의 길이를 출력하는 것이 아니라, 신장 트리를 구성하는 간선이 "노드의 개수 - 1"인지 확인하여야 한다.
이 조건을 만족하지 못하면 -1을 출력하도록 한다.
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
/* BOJ 나만 안되는 연애 */
/* MST - 크루스칼 */
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <string.h>
#define endl '\n'
using namespace std;
typedef long long ll;
int n, m, p[1001];
char school_types[1001];
vector<pair<pair<int, int>, int>> edges;
// find
int find_parent(int x)
{
if (p[x] == x)
return x;
return p[x] = find_parent(p[x]);
}
// union
void union_parent(int a, int b)
{
a = find_parent(a);
b = find_parent(b);
if (a < b)
p[a] = b;
else
p[b] = a;
}
bool cmp(pair<pair<int, int>, int> p1, pair<pair<int, int>, int> p2)
{
return p1.second < p2.second;
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
// freopen("input.txt", "r", stdin);
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
p[i] = i; // 부모 배열 초기화
cin >> school_types[i];
}
for (int i = 0; i < m; i++)
{
int u, v, d;
cin >> u >> v >> d; // u <-> v는 d만큼 떨어짐
if (school_types[u] != school_types[v]) // 남초<->남초 또는 여초<->여초가 아닌 경우
edges.push_back({ {u, v}, d }); // 유의미한 간선이므로 간선그룹에 포함
}
sort(edges.begin(), edges.end(), cmp); // 간선들의 비용 기준 오름차순 정렬
int ans = 0, cnt = 0;
for (auto edge : edges)
{
int u = edge.first.first;
int v = edge.first.second;
int d = edge.second;
if (find_parent(u) != find_parent(v))
{
// u와 v가 다른 집합에 속한다면, 즉 싸이클을 발생시키지 않는다면
union_parent(u, v);
ans += d;
if (++cnt == n - 1) // 모든 대학들을 다 갈 수 있기 위해서는 (노드수-1)의 간선이 필요
{
cout << ans << endl;
return 0;
}
}
}
cout << -1 << endl; // 모든 대학을 연결하는 MST 찾지 못하면 -1 출력
return 0;
}
|
cs |
'알고리즘 BOJ' 카테고리의 다른 글
백준(BOJ) 14499 주사위 굴리기 C++ 풀이 (0) | 2021.06.29 |
---|---|
백준(BOJ) 1182 부분 수열의 합 C++ 풀이 (0) | 2021.06.29 |
백준(BOJ) 11728 배열 합치기 C++ 풀이 (0) | 2021.06.27 |
백준(BOJ) 9342 염색체 C++ 풀이 (0) | 2021.06.27 |
백준(BOJ) 1316 그룹 단어 체커 C++ 풀이 (0) | 2021.06.24 |
Comments