본문 바로가기

알고리즘/백준

백준 1949 우수 마을

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

 

1949번: 우수 마을

N개의 마을로 이루어진 나라가 있다. 편의상 마을에는 1부터 N까지 번호가 붙어 있다고 하자. 이 나라는 트리(Tree) 구조로 이루어져 있다. 즉 마을과 마을 사이를 직접 잇는 N-1개의 길이 있으며, ��

www.acmicpc.net

 

Tree Dp 문제

 

돌이켜생각해보면 tree는 참 재밌는 구석이 많은 자료구조같다. 지름 구하는 것도 참 신기하고...

 

양방향 간선이므로 어떤 노드를 root로 선택해도 된다. 그래서 생각하기 편하도록 1번 노드를 Root 노드로 잡았다. 

 

어떤 분은 트리 순회하는 순서를 처음부터 vector에 저장하시던데, 내 코드는 그러진 않았다.

 

코드를 보면 이해가 더 잘되실 것 같다.

 

/* 우수 마을 */

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void input();
void solve();

int N, weight[10000 + 1], Ans;
int treeDp[10000 + 1][2];

vector<int> house[10001];

int main(void) {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	
	input();
	solve();

	return 0;
}

void input() {
	cin >> N;
	for (int i = 1; i <= N; i++)
		cin >> weight[i];

	for (int i = 1; i < N; i++) {
		int a, b; cin >> a >> b;

		house[a].push_back(b);
		house[b].push_back(a);
	}
}

int recur( int curr, bool include, int before) {
	int& ret = treeDp[curr][include];

	// 중복은 뺀다. 
	if (ret != 0) {
		return ret;
	}

	int summation = 0;
	// 현재 마을은 우수 마을이다.
	if (include) {
		summation += weight[curr];

	/* 현재 마을이 우수 마을이면 다음 마을은 무조건 우수마을이 아니다. */
		for (auto nxt_node : house[curr]) {
			if (nxt_node == before) continue;
			summation += recur( nxt_node, false, curr);
		}
	}
	
	// 현재 마을은 우수 마을이 아니다.
	else {
		for (auto nxt_node : house[curr]) {
			if (nxt_node == before) continue;

	/* 현재 마을이 우수 마을이 아닐 때, 다음 마을은 우수 마을일 수도 있고 아닐 수도 있다.*/
	/* 만약 우수 마을이 아닌 경우가 세 번 이상이면 어떡하는가, 질문이 나올 수도 있지만 
	   하나의 마을이라도 더 포함하는 게 주민 수를 늘리기 때문에 세 번 연속 우수마을이 아닌 경우보다
	   적어도 하나의 마을이 우수마을이 더 많은 주민을 포함하고, 정답이다.
	   그러므로 세 번 연속 우수마을이 아닌 경우를 따로 처리하는 로직을 넣지 않았다. 
	*/
			summation += max(recur(nxt_node, true, curr), recur(nxt_node, false, curr));
		}
	}

	return ret = summation;
}

 void solve() { 
	 // 첫번째 마을이 우수마을인 경우 vs 우수마을이 아닌 경우
	 Ans = max(recur(1, true, -1), recur(1, false, -1));

	 cout << Ans << '\n';
}

'알고리즘 > 백준' 카테고리의 다른 글

백준 1963 소수 경로  (0) 2020.08.23
백준 11438 LCA2  (0) 2020.08.23
백준 3109 빵집  (0) 2020.08.22
백준 2263 트리의 순회  (0) 2020.08.21
백준 11437 LCA  (0) 2020.08.18