※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 1623번 문제인 신년 파티이다.
문제는 아래 링크를 확인하자.

https://www.acmicpc.net/problem/1623 

 

1623번: 신년 파티

첫째 줄에 사장을 포함한 모든 직원의 수 N이 주어진다. (2≤N≤200,000) 사장은 1번이며, 다른 직원들은 2번부터 N번까지 차례로 번호가 매겨져 있다. 둘째 줄에는 사장을 포함한 모든 직원의 "날라

www.acmicpc.net

최적해를 가질 때의 그 구성 노드를 역추적한 결과를 요구하는 DP문제이다.

 

노드i를 사용하지 않을 때 노드i를 루트로 갖는 서브트리의 "날라리 분위기"의 최댓값을 dp0[i], 노드i를 사용할 때 노드i를 루트로 갖는 서브트리의 "날라리 분위기"의 최댓값을 dp1[i]로 표현하면, 전체 트리의 리프노드서부터 루트방향으로 위상정렬순으로 모든 노드를 순회하며 dp0[i]와 dp1[i]값을 채워나가는 것으로 최적해를 구해낼 수 있다.

 

이 때, 어떤 dp0[j] 또는 dp1[j]가  dp0[i]의 값에 영향을 주었는지와 dp1[i]의 값에 영향을 주었는지를 인접리스트의 형태로 보관해, 해당 인접리스트를 이용하여 답을 역추적해낼 수 있다.

 

문제에서 주어지는 "날라리 기질"은 음수값이 주어질 수 있음에 유의하여 구현하자.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;

int parent[200001];
int indegree[200001];
int dp0[200001], dp1[200001];
vector<pair<int,int>> dp0node[200001], dp1node[200001]; // {자식노드, 0/1}

vector<int> ans;

void backtrack1(int cur);

void backtrack0(int cur) {
	for (auto node : dp0node[cur]) {
		if (node.second) backtrack1(node.first);
		else backtrack0(node.first);
	}
}

void backtrack1(int cur) {
	ans.emplace_back(cur);
	for (auto node : dp1node[cur]) {
		backtrack0(node.first);
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	int N; cin >> N;
	for (int i = 1; i <= N; i++) cin >> dp1[i];
	for (int i = 2; i <= N; i++) {
		int& tmp = parent[i];
		cin >> tmp;
		indegree[tmp]++;
	}

	queue<int> que;
	for (int i = 1; i <= N; i++) {
		if (indegree[i] == 0) que.push(i);
	}

	while (!que.empty()) {
		int cur = que.front(); que.pop();
		int par = parent[cur];
		
		if (dp0[cur] >= dp1[cur] && dp0[cur] > 0) {
			dp0[par] += dp0[cur];
			dp0node[par].emplace_back(make_pair(cur, 0));
		}
		else if (dp1[cur] > dp0[cur] && dp1[cur] > 0) {
			dp0[par] += dp1[cur];
			dp0node[par].emplace_back(make_pair(cur, 1));
		}

		if (dp0[cur] > 0) {
			dp1[par] += dp0[cur];
			dp1node[par].emplace_back(make_pair(cur, 0));
		}

		indegree[par]--;
		if (indegree[par] == 0) que.push(par);
	}

	cout << dp1[1] << ' ' << dp0[1] << '\n';

	backtrack1(1);
	sort(ans.begin(), ans.end());
	for (auto x : ans) cout << x << ' ';
	cout << -1 << '\n';
	
	ans.clear();
	backtrack0(1);
	sort(ans.begin(), ans.end());
	for (auto x : ans) cout << x << ' ';
	cout << -1 << '\n';
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 2078 // C++] 무한이진트리  (0) 2022.05.27
[BOJ 1835 // C++] 카드  (0) 2022.05.26
[BOJ 21219 // C++] Restaurants  (0) 2022.05.24
[BOJ 3761 // C++] The Stable Marriage Problem  (0) 2022.05.23
[BOJ 12718 // C++] Crop Triangles (Large)  (0) 2022.05.22

+ Recent posts