[문제링크]

 

2533번: 사회망 서비스(SNS)

첫 번째 줄에는 친구 관계 트리의 정점 개수 N이 주어진다. 단, 2 ≤ N ≤ 1,000,000이며, 각 정점은 1부터 N까지 일련번호로 표현된다. 두 번째 줄부터 N-1개의 줄에는 각 줄마다 친구 관계 트리의 에

www.acmicpc.net

 

0. 모든 친구가 얼리-어답터라면 자신도 어답터가 된다

  • 얼리-어답터가 아닌 두 사람이 친구라면, 이 둘은 어떤 일이 있어도 얼리-어답터가 되지 못한다

 

1. 어떤 사람(노드)를 기준으로, 이 사람이 얼리 어답터가 아니려면 이 사람과 친구인 모든 사람이 얼리-어답터여야만 한다

 

2. 반대로, 어떤 사람이 얼리-어답터이라면 친구의 얼리-어답터 유무는 중요하지 않다

  • 친구의 친구가 얼리 어답터가 아니라면 문제가 생기겠지만, 이건 해당 친구 노드를 처리할 때 처리하고, 우선 직접 연결된 친구만 고려한다

 

3. 친구 없는 사람이라면, 자신이 얼리 어답터인지/아닌지에 조건이 붙지 않는다

 

4. 특정 사람(노드)을 root로 삼는 subtree 기준으로,

  • 이 사람이 얼리-어답터이기 위한 최소 어답터 필요량
    • 3번 정의에 따르면, 친구(자식 노드)의 얼리-어답터 유무는 중요하지 않다
  • 얼리어답터가 아니기 위한 최소 어답터 필요량
    • 2번 정의에 따르면, 모든 친구(자식)은 얼리-어답터여야 한다
  • 이 두가지를 반환한다
  • leaf 노드는 제한이 없으므로 얼리 어답터일때 1, 아닐때 0을 반환한다

 

5. 즉, 특정 사람(노드)이 얼리-어답터일 때 필요한 최소 어답터 수는

  • 모든 자식들의 얼리/not-얼리 결과값 중 작은것의 합계 + 1(자기 자신) 이 된다

 

6. 특정 사람(노드)이 얼리-어답터가 아닐 때 필요한 최소 어답터 수는

  • 모든 자식을듸 얼리 결과값의 합계 가 된다

 

7. 이 과정을 leaf 노드부터 시작해 root노드까지 진행하면, root가 얼리-어답터일때 / 아닐때 각각의 최솟값을 구할 수 있다

  • 둘 중 작은 값을 반환한다

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

public class Main {
	static boolean[] isVisit;
	static List<List<Integer>> tree;
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		int N = pint(br.readLine());
		tree = new ArrayList<>();
		for (int i = 0; i < N; i++) {
			tree.add(new LinkedList<Integer>());
		}
		for (int i = 0; i < N-1; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
			int n = pint(st.nextToken()) - 1;
			int m = pint(st.nextToken()) - 1;
			
			tree.get(n).add(m);
			tree.get(m).add(n);
		}
		
		isVisit = new boolean[N];
		int curNode=0;
		isVisit[curNode]=true;
		int[] ans = rec(curNode);
		System.out.println(ans[0]>ans[1]?ans[1]:ans[0]);
	}
	
	static int[] rec(int curNode) {
		if(curNode!=0 && tree.get(curNode).size()==1) {
			return new int[] {1,0};
		}
		int iAmEA=1;
		int iAmNotEA=0;
		for(int nextNode : tree.get(curNode)) {
			if(isVisit[nextNode])continue;
			isVisit[nextNode]=true;
			int[] tmp = rec(nextNode);
			
			iAmEA += Math.min(tmp[1],tmp[0]);
			iAmNotEA += tmp[0];
		}
		
		return new int[]{iAmEA,iAmNotEA};
	}
	
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

+ Recent posts