티스토리 뷰
https://www.acmicpc.net/problem/2533
2533번: 사회망 서비스(SNS)
첫 번째 줄에는 친구 관계 트리의 정점 개수 N이 주어진다. 단, 2 ≤ N ≤ 1,000,000이며, 각 정점은 1부터 N까지 일련번호로 표현된다. 두 번째 줄부터 N-1개의 줄에는 각 줄마다 친구 관계 트리의 에
www.acmicpc.net
문제
페이스북, 트위터, 카카오톡과 같은 사회망 서비스(SNS)가 널리 사용됨에 따라, 사회망을 통하여 사람들이 어떻게 새로운 아이디어를 받아들이게 되는가를 이해하는 문제가 중요해졌다. 사회망에서 사람들의 친구 관계는 그래프로 표현할 수 있는데, 이 그래프에서 사람은 정점으로 표현되고, 두 정점을 잇는 에지는 두 정점으로 표현되는 두 사람이 서로 친구 관계임을 표현한다.
예를 들어, 철수와 영희, 철수와 만수, 영희와 순희가 서로 친구 관계라면 이를 표현하는 친구 관계 그래프는 다음과 같다.
친구 관계 그래프를 이용하면 사회망 서비스에서 어떤 새로운 아이디어가 전파되는 과정을 이해하는데 도움을 줄 수 있다. 어떤 새로운 아이디어를 먼저 받아들인 사람을 얼리 아답터(early adaptor)라고 하는데, 사회망 서비스에 속한 사람들은 얼리 아답터이거나 얼리 아답터가 아니다. 얼리 아답터가 아닌 사람들은 자신의 모든 친구들이 얼리 아답터일 때만 이 아이디어를 받아들인다.
어떤 아이디어를 사회망 서비스에서 퍼뜨리고자 할 때, 가능한 한 최소의 수의 얼리 아답터를 확보하여 모든 사람이 이 아이디어를 받아들이게 하는 문제는 매우 중요하다.
일반적인 그래프에서 이 문제를 푸는 것이 매우 어렵다는 것이 알려져 있기 때문에, 친구 관계 그래프가 트리인 경우, 즉 모든 두 정점 사이에 이들을 잇는 경로가 존재하면서 사이클이 존재하지 않는 경우만 고려한다.
예를 들어, 8명의 사람으로 이루어진 다음 친구 관계 트리를 생각해보자. 2, 3, 4번 노드가 표현하는 사람들이 얼리 아답터라면, 얼리 아답터가 아닌 사람들은 자신의 모든 친구가 얼리 아답터이기 때문에 새로운 아이디어를 받아들인다.
친구 관계 트리가 주어졌을 때, 모든 개인이 새로운 아이디어를 수용하기 위하여 필요한 최소 얼리 어답터의 수를 구하는 프로그램을 작성하시오.
유형 : 트리 + DP
접근 방식
- 반대로 생각을 해봤다.
- 최대로 많이 칠했을 때 해당 개수가 의미하는 것은 무엇일까?
- 인접하지 않게 칠하여 모든 경우를 만족하는 것이다.
- 그렇다면 모든 정점의 개수인 n에서 최대 칠하는 개수를 뺀다면?
- 나머지 정점들로만 최소의 개수로 모든 조건을 만족할 수 있다는 것이다.
전체 코드
import java.util.*;
import java.io.*;
public class Main {
static int n = 0;
static ArrayList<Integer>[] graph;
static int[] p;
static int[][] dp;
public static void main(String[] args) throws Exception {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(bf.readLine(), " ");
//StringBuilder sb = new StringBuilder();
n = Integer.parseInt(st.nextToken());
graph = new ArrayList[n+1];
p = new int[n+1];
dp = new int[n+1][2];
// (i,0) -> 자신을 칠하지 않았을 때 최댓값
// (i,1) -> 자신을 칠했을 때 최댓값
for(int i=1;i<=n;i++){
graph[i] = new ArrayList<>();
}
for(int i=1;i<=n-1;i++){
st = new StringTokenizer(bf.readLine(), " ");
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
graph[x].add(y);
graph[y].add(x);
}
dfs(1);
// 전체 개수에서 최대 칠하는 개수를 뺀다면 나머지 개수를 가장 최소로 전부 칠할 수 있다.
System.out.println(n - Math.max(dp[1][0],dp[1][1]));
bf.close();
}
static void dfs(int cur){
for(int next : graph[cur]){
if(p[cur] == next){continue;}
p[next] = cur;
dfs(next);
dp[cur][0] += Math.max(dp[next][0],dp[next][1]); // 자신을 안칠했을 때 다음꺼의 최댓값
dp[cur][1] += dp[next][0]; // 자신을 칠하면 다음은 무조건 안칠한다.
}
dp[cur][1] += 1; // 자신은 무조건 칠한다.
}
}
'알고리즘 > 백준' 카테고리의 다른 글
백준 1185 (유렵여행) - java (1) | 2024.01.25 |
---|---|
백준 11909 (배열 탈출) - java (0) | 2024.01.22 |
백준 23034 (조별과제 멈춰!) - java (0) | 2024.01.17 |
백준 1167 (트리의 지름) - java (0) | 2024.01.15 |
백준 2450 (모양 정돈) - java (0) | 2024.01.15 |
- Total
- Today
- Yesterday
- 백준 #
- 백준 #18405 #경쟁적 전염
- 백준 #1325 #효율적인 해킹
- 백준 #1584 #게임 #java #자바
- 백준 #17940 #주식 #자바 #java
- 백준 #28140 #빨강~ 빨강~ 파랑! 파랑! 달콤한 솜사탕! #java #자바
- 백준 #3980 #선발 명단
- 백준 #다리 만들기 #2146
- 백준 #2636 #치즈
- 백준 #25603 #짱해커 이동식 #java #자바
- Java
- 백준 #15686 #치킨 배달
- 백준 #16973 #직사각형 탈출
- 백준 #1987 #알파벳 #자바 #java
- 자바 #JAVA
- 17394
- 백준 #14863 #서울에서 경산까지 #java #자바
- 백준 #5721 #사탕 줍기 대회 #java #자바
- 백준
- 백준 #12014 #주식 #자바 #java
- 백준 #치즈 #2638
- 백준 #4963 #섬의 개수
- 백준 #2580 #스도쿠
- 자바
- 17218
- 백준 #25195 #yes or yes #java #자바
- 백준 #인구 이동 #16234
- 백준 #1727 #커플 만들기 #자바 #java
- 백준 #1759 #암호 만들기
- 백준 #13549 #숨바꼭질3
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |