문제링크 : https://www.acmicpc.net/problem/2213
2213번: 트리의 독립집합
첫째 줄에 트리의 정점의 수 n이 주어진다. n은 10,000이하인 양의 정수이다. 1부터 n사이의 정수가 트리의 정점이라고 가정한다. 둘째 줄에는 n개의 정수 w1, w2, ..., wn이 주어지는데, wi는 정점 i의
www.acmicpc.net
접근 과정 :
- 이전에 풀었던, '트리에서의 다이나믹 프로그래밍' 접근을 통해서 문제를 해결하려고 했다.
- 추가적으로 고민했던 부분은 독립 집합의 원소들을 추적하는 부분이었다.
- 결국 현재 정점의 독립 집합 포함 여부에 따라서 연결된 다음 정점의 포함여부가 결정되기에, 이 부분을 고려해서 작성했다.
- DP[][] : i번 정점의 독립집합 포함 여부 , [n+1][2]
소스 코드 및 결과 :
package BOJ;
/*
트리의 독립집합
*/
import java.io.*;
import java.util.*;
public class BOJ2213 {
public static void main(String[] args) throws NumberFormatException, IOException {
init();
findDP(1);
StringBuilder answer = new StringBuilder();
group = new ArrayList<>();
visit = new boolean[n+1];
if (dp[1][0]> dp[1][1]) {
answer.append(dp[1][0]).append("\n");
trace(1, false);
}else{
answer.append(dp[1][1]).append("\n");
trace(1, true);
}
Collections.sort(group);
for(int v : group){
answer.append(v).append(" ");
}
System.out.println(answer.toString().trim());
}
static int n;
static int[] w;
static Node[] G;
static int[][] dp; // i의 독립 집합 여부에 따른 최대 가중치
static boolean[] visit;
static List<Integer> group;
static void init() throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
n = Integer.parseInt(br.readLine());
w = new int[n + 1];
st = new StringTokenizer(br.readLine());
for (int i = 1; i <= n; i++) {
w[i] = Integer.parseInt(st.nextToken());
}
G = new Node[n + 1];
for (int i = 1; i < n; i++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
insert(a, b);
insert(b, a);
}
dp = new int[n + 1][2];
visit = new boolean[n + 1];
}
private static class Node {
int num;
Node parent;
Node(int num, Node parent) {
this.num = num;
this.parent = parent;
}
}
static void insert(int p, int c) {
if (G[p] == null) {
G[p] = new Node(c, null);
} else {
G[p] = new Node(c, G[p]);
}
}
static void findDP(int x) {
visit[x] = true;
dp[x][1] = w[x];
Node v = G[x];
while (v != null) {
if (visit[v.num]) {
v = v.parent;
continue;
}
findDP(v.num);
dp[x][0] += Math.max(dp[v.num][0], dp[v.num][1]);
dp[x][1] += dp[v.num][0];
v = v.parent;
}
}
static void trace(int x, boolean state) {
visit[x] = true;
if (state) {
group.add(x);
Node v = G[x];
while (v != null) {
if (visit[v.num]) {
v = v.parent;
continue;
}
trace(v.num, false);
v = v.parent;
}
} else {
Node v = G[x];
while (v != null) {
if (visit[v.num]) {
v = v.parent;
continue;
}
if (dp[v.num][1] > dp[v.num][0]) {
trace(v.num, true);
} else {
trace(v.num, false);
}
v = v.parent;
}
}
}
}
P.S
사실 트리관련 문제를 조금 어려워하는 편이다.
아무래도, 트리 구조를 활용하려면 클래스를 작성해야 하고 필요한 메소드를 직접 만들어야 해서 약간의 부담감을 느끼는 것 같다.
특히 코딩테스트를 할 때에는 새로운 클래스 생성을 좀 지양하는 편이다..
이번 문제 역식, 최근에 트리에서의 DP 활용문제를 많이 풀면서 머리에 때려박아서 가능하지 않았나 싶다..
미래의 내가 이러한 문제를 다시 풀어도 비슷하게 접근할 수 있기를 바래본다.
'Algorithm' 카테고리의 다른 글
[백준 Silver 3] 10825 국영수 - Java (1) | 2022.01.07 |
---|---|
[백준 Silver 3] 3085 사탕 게임 - Java (0) | 2022.01.07 |
[백준 Gold 1] 1949 우수 마을 - Java (0) | 2022.01.05 |
[백준 Gold 3] 2553 사회망 서비스(SNS) - Java (0) | 2022.01.05 |
[백준 Platinum 5] 2618 경찰차 - Java (0) | 2022.01.04 |