풀이 방법
이 문제는 트리에서의 dp문제 이다.
저는 맞왜틀을 외치다 여기 를 참고했습니다. 우선 dfs를 이용하여 임의의 루트를 정하여 그 트리의 경로를 저장합니다.
dp정의는 dp[현재 노드][현재 노드를 포함하는가 여부]로 정의하고, 만약 현재 노드를 포함한다면 자식 노드는 포함 할 수 없고, 포함하지 않는다면 자식노드를 포함하든 안하든 상관이 없다.
포함하는 경로 추적은 루트 노드부터 시작해서 dfs를 돌며 dpf를 돌때 저장한 배열의 값이 true인 경우를 ans배열에 저장한다.
코드
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int cost[10004], dp[10004][2], check[10004], res;
vector<vector<int>> v, tree;
vector<int> ansarr;
void dfs(int cur, int prv) {
for (auto nxt : v[cur]) {
if (nxt != prv) {
tree[cur].push_back(nxt);
dfs(nxt, cur);
}
}
}
int dpf(int cur, bool include) {
int &res = dp[cur][include];
if (res != -1) return res;
if (include) {
int ans = 0;
for (auto nxt : tree[cur]) ans += dpf(nxt, 0);
return res = ans + cost[cur];
} else {
int ans = 0;
for (auto nxt : tree[cur]) {
int t1 = dpf(nxt, 0);
int t2 = dpf(nxt, 1);
if (t1 < t2) check[nxt] = 1;
else check[nxt] = 0;
ans += max(t1, t2);
}
return res = ans;
}
}
void track(int cur, int include) {
if (include) {
ansarr.push_back(cur);
for (auto nxt : tree[cur]) track(nxt, 0);
} else {
for (auto nxt : tree[cur]) track(nxt, check[nxt]);
}
}
int main() {
int N; scanf("%d", &N);
v.resize(N + 1);
tree.resize(N + 1);
for (int i = 1; i <= N; i++) {
scanf("%d", cost + i);
dp[i][0] = dp[i][1] = -1;
}
for (int i = 0; i < N - 1; i++) {
int a, b; scanf("%d %d", &a, &b);
v[a].push_back(b); v[b].push_back(a);
}
dfs(1, 1);
int t1 = dpf(1, 0);
int t2 = dpf(1, 1);
if (t1 < t2) check[1] = 1;
else check[1] = 0;
printf("%d\n", max(t1, t2));
track(1, check[1]);
sort(ansarr.begin(), ansarr.end());
for (auto iter : ansarr) printf("%d ", iter);
}
'Algorithm > BOJ' 카테고리의 다른 글
백준[1949] 우수마을 (0) | 2021.06.29 |
---|---|
백준[2533] 사회망 서비스(SNS) (0) | 2021.06.24 |
백준[2887] 행성터널 (0) | 2021.06.22 |
백준[1774] 우주신과의 교감 (0) | 2021.06.22 |
백준[4386] 별자리 만들기 (0) | 2021.06.22 |