[BOJ][실1][1068] 트리
문제 링크
첫 번째 풀이 : DFS
알고리즘
인접리스트로 정보를 저장한 후 전체 리프 노드의 갯수를 count합니다. 그리고 지우려하는 노드부터 dfs를 진행해서 leaf 노드의 갯수만큼 뺍니다. 이 때 지운 노드에 의해서 지운 노드의 부모가 leaf가 되는지 추가적으로 확인해야 합니다.
정답 코드
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
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
vector<int> v[50];
vector<bool> visited(50, false);
vector<int> root;
int ans = 0;
void dfs(int x) {
visited[x] = true;
bool flag = true; // 리프노드이면 true
for (int i = 0; i < v[x].size(); i++) {
int next = v[x][i];
if (!visited[next]) {
dfs(next);
flag = false;
}
}
if (flag)ans--;
}
int main()
{
//freopen("input.txt", "r", stdin);
ios_base::sync_with_stdio(0); cin.tie(0);
cin >> n;
int t = 0;
for (int i = 0; i < n; i++) {
cin >> t;
if (t == -1) {
root.push_back(i);
}
else {
// t는 i의 부모
v[t].push_back(i);
}
}
for (int i = 0; i < n; i++) {
if (v[i].size() == 0) ans++;
}
cin >> t;
dfs(t);
for (int i = 0; i < n; i++) {
if (v[i].size() == 1 && v[i][0] == t) ans++;
}
cout << ans << "\n";
return 0;
}
두 번째 풀이 : dfs
알고리즘
그래프를 문제에서 주어진 그대로, 각 노드의 부모 노드 번호를 저장하는 형태로 사용합니다.
추가적인 설명은 주석으로 남겨놨습니다.
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
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
int p[50]; // parent number
int c[50]; // # of child
// 현재 노드를 지운다
void dfs(int x) {
// 부모의 자식을 1개 줄인다
if (p[x] != -1) {
c[p[x]]--;
}
// 현재 노드의 부모를 없애기
c[x] = -1;
// 자식노드도 같은 과정 반복하기
for (int i = 0; i < n; i++) {
if (p[i] == x) {
dfs(i);
}
}
}
int main()
{
//freopen("input.txt", "r", stdin);
ios_base::sync_with_stdio(0); cin.tie(0);
cin >> n;
for (int i = 0; i < n; i++) {
cin >> p[i];
if (p[i] != -1) {
c[p[i]]++; // 부모가 가지는 자식의 갯수 + 1
}
}
int d = 0;
cin >> d;
dfs(d);
int ans = 0;
for (int i = 0; i < n; i++) {
if (c[i] == 0) ans++;
}
cout << ans;
return 0;
}
세 번째 풀이 : DFS
알고리즘
그래프에서 특정 노드를 삭제하는 유형을 자주 나옵니다. 세 번째 풀이는 삭제하려고 하는 노드를 미리 방문했다고 처리하고, 방문한 곳은 dfs를 더이상 진행하지 않도록 해서 leaf의 갯수를 파악하는 방법입니다.
소스 코드
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
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
vector<int> v[50];
vector<bool> visited(50, false);
int root = 0;
int ans = 0;
void dfs(int x) {
// 이미 방문한 노드인 경우 종료
if (visited[x]) return;
// 노드방문
visited[x] = true;
bool flag = true; // 리프노드이면 true
for (int i = 0; i < v[x].size(); i++) {
int next = v[x][i];
if (!visited[next]) {
dfs(next);
flag = false; // 방문하지 않는 자식 노드가 있는 경우
}
}
if (flag)ans++;
}
int main()
{
//freopen("input.txt", "r", stdin);
ios_base::sync_with_stdio(0); cin.tie(0);
cin >> n;
int t = 0;
for (int i = 0; i < n; i++) {
cin >> t;
if (t == -1) {
root = i;
}
else {
// t는 i의 루트
v[t].push_back(i);
}
}
cin >> t;
// 지워야하는 노드 방문처리
visited[t] = true;
dfs(root);
cout << ans << "\n";
return 0;
}
Success Notice: 수고하셨습니다.
Leave a comment