본문 바로가기

문제 노트/백준

Visiting Cows( BOJ 5934 )

5934. Visiting Cows : https://www.acmicpc.net/problem/5934

 

5934번: Visiting Cows

After many weeks of hard work, Bessie is finally getting a vacation! Being the most social cow in the herd, she wishes to visit her N (1 <= N <= 50,000) cow friends conveniently numbered 1..N. The cows have set up quite an unusual road network with exactly

www.acmicpc.net

 

문제 파악하기

  • Bessie에게는 친한 소가 N마리 있으며, N마리의 소 사이에는 트리 형태로 길이 연결되어 있습니다.
  • 농부 John은 Bessie에게 이미 만난 소와 인접한 소는 만나선 안 된다고 했습니다.
  • 방학을 얻은 Bessie는 N마리의 소를 최대한 많이 만나고 싶어합니다.

 

문제 해결하기

  • 문제를 풀기 위해서는 우선 트리 형태로 입력 데이터를 바꿔야 합니다. 이 때, 재귀함수를 사용할 수 있습니다.
  • 트리 형태로 바꾼 이후에는 각각의 소(노드)에 대해 2가지 경우의 수를 생각할 수 있습니다.
    1. 현재 노드를 방문하고, 자식 노드를 방문하지 않는 경우
    2. 현재 노드를 방문하지 않고, 자식 노드를 방문하거나 방문하지 않는 경우
  • 1번 경우에는 모든 자식 노드가 선택되지 않았을 때, 나올 수 있는 경우를 살펴보면 됩니다.
    2번 경우에는 모든 자식 노드에 대해 나올 수 있는 2가지 경우 중 더 큰 경우를 살펴보면 됩니다.
  • 따라서, 현재 노드의 방문 여부에 따른 DP를 적용하면 문제를 해결할 수 있습니다.
    dp[idx][0]: idx번 노드를 방문하지 않은 경우 / dp[idx][1]: idx번 노드를 방문한 경우

 

소스코드

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
#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
#define NMAX 50010
using namespace std;
 
// 입력 변수
int n, a, b;
vector< int > graph[NMAX];
 
// 트리 변수
int check[NMAX];
vector< int > tree[NMAX];
 
// DP 변수
int dp[NMAX][2];
 
void make_tree(int idx) {
    for(int child:graph[idx]) {
        if(check[child]) continue;
 
        check[child] = 1;
        tree[idx].push_back(child);
 
        make_tree(child);
    }
}
 
int sv(int idx, int sw) {
    int ret=0;
 
    if(dp[idx][sw] >= 0return dp[idx][sw];
 
    // sw: idx번 노드를 방문했는지 여부
    for(int child:tree[idx]) {
        if(sw == 1) ret += sv(child, 0);
        else ret += max(sv(child, 0), sv(child, 1)+1);
    }
 
    return dp[idx][sw] = ret;
 
}
 
int main() {
    // 입력
    scanf("%d"&n);
    for(int i=1;i<n;i++) {
        scanf("%d %d"&a, &b);
 
        graph[a].push_back(b);
        graph[b].push_back(a);
    }
 
    // 트리 만들기
    check[1= 1;
    make_tree(1);
 
    // DP
    memset(dp, -1sizeof(dp));
    printf("%d", max(sv(10), sv(11)+1));
 
}
cs

 

후기

가장 기본적인 트리 DP 문제라고 생각합니다. 트리를 구현하고 DP를 적용하는데 어려움이 없기 때문에 트리를 연습하는 사람들에게 추천하고 싶은 문제입니다.

'문제 노트 > 백준' 카테고리의 다른 글

248 게임( BOJ 12031 )  (0) 2021.06.29
크리스마스 트리 꾸미기( BOJ 16468 )  (0) 2021.06.21
금고 (SAFE) ( BOJ 14932 )  (0) 2021.04.10
구간 합 구하기( BOJ 2042 )  (0) 2021.03.24
구간 합 구하기 4( BOJ 11659 )  (0) 2021.03.18