리뷰
트리에서의 다이나믹 프로그래밍을 활용하여 얼리어답터의 최소 갯수를 구하는 문제
https://www.acmicpc.net/problem/2533
전역 변수
- n : 노드의 개수
- lst : 인접 리스트를 통해 노드간 양방향 간선 정보를 저장할 2차원 정수형 벡터
- dp : 각 노드가 얼리어답터일때와 아닐때의 정보를 저장할 배열
- v : dfs탐색 시 노드의 방문 정보를 저장할 배열
함수
1. dfs
void dfs(int cn)
- 깊이 우선 탐색을 통해 얼리어답터의 개수를 재귀적으로 구해줄 함수
- 현재 노드를 매개변수를 통해 전달받고, 각 인접리스트의 노드를 매개변수로 전달해 준다.
- 함수 실행 시 현재 노드가 얼리어답터일때는 1, 아닐때는 0으로 초기값을 세팅해 준다.
- 인접리스트를 순회하고 자식 노드가 방문하지 않았을 경우 우선적으로 재귀를 수행한다.
- 재귀를 빠져나온 후 현재 노드의 얼리어답터가 아닐 경우 자식 노드가 얼리어답터일 경우의 값을 더해준다.
- 현재 노드가 얼리어답터일 경우 자식 노드가 얼리어답터가 아닐 경우와 맞을 경우 중 최소값을 더해준다.
- 모든 재귀가 종료된다면 루트 노드에 얼리어답터일 경우와 아닐 경우의 값이 모두 저장된다.
문제풀이
- n값을 입력 받고, 인접리스트를 저장할 벡터를 n + 1크기로 저장해 준다.
- n - 1개의 간선 정보를 입력 받아 양방향 간선으로 추가해 준다.
- 루트 노드에 방문처리를 해준 후 루트로부터 깊이 우선 탐색을 진행해 준다.
- 1번 노드가 얼리어답터인 경우와 아닐 경우의 최소값을 구해 출력해 준다.
참고 사항
1-based-indexing이므로 인접 리스트를 n + 1크기로 설정해 주었다.
dp정보는 dfs함수가 실행되었을때 자기자신을 한번 초기화 해주고, 자식노드의 재귀가 마친 후에 추가 작접을 해준다.
정답 코드
#include<iostream>
#include<vector>
using namespace std;
int n;
vector<vector<int>> lst;
int dp[1000001][2];
int v[1000001];
void dfs(int cn) {
dp[cn][0] = 0;
dp[cn][1] = 1;
for (int nn : lst[cn]) {
if (v[nn]) continue;
v[nn] = 1;
dfs(nn);
dp[cn][0] += dp[nn][1];
dp[cn][1] += min(dp[nn][0], dp[nn][1]);
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n;
lst.resize(n + 1);
for (int i = 0; i < n - 1; i++) {
int n1, n2; cin >> n1 >> n2;
lst[n1].push_back(n2);
lst[n2].push_back(n1);
}
v[1] = 1;
dfs(1);
cout << min(dp[1][0], dp[1][1]);
}
728x90
'알고리즘 공부 > C++' 카테고리의 다른 글
[P4] 백준 3653번 영화 수집 C++ 세그먼트 트리 (1) | 2024.10.07 |
---|---|
[P5] 백준 7578번 공장 C++ 세그먼트 트리 (0) | 2024.10.06 |
[D3] SWEA 22683번 나무 베기 C++ 다익스트라, 최단 경로 (0) | 2024.10.06 |
[G3] 백준 14725번 개미굴 C++ 트라이, 문자열 (1) | 2024.10.06 |
[G3] 백준 17299번 오등큰수 C++ 스택 (0) | 2024.10.05 |