본문 바로가기
ps연습장

백준 2533번 : 사회망 서비스(SNS) (C/C++)

by hwsyl 2023. 5. 9.
반응형

<문제>

백준 2533번

 

<풀이>

최소 얼리 어댑터의 수를 구하는 문제이다. 전형적인 트리dp문제라고 볼 수 있다.

이문제를 풀기 위해서는 트리는 트리로 구성되어있다는 개념을 이용해야한다.

 

우선 k=1을 얼리 어댑터, k=0인 경우를 얼리 어댑터가 아닌 경우라고 할때,

dp 배열을 아래와 같이 정의한다.

 

dp[n][k] : n이 k이고, n을 루트로하는 서브트리의 최소 얼리 어댑터의 수

 

1. k=1일때,

  자식 노드들이 1이여도 되고, 0이여도된다. n의 모든 자식 노드를 nx라고 할때, 다음이 성립한다.

 

2. k=0일때,

 모든 자식 노드들이 1이여야만 한다. 

<코드>

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<bits/stdc++.h>
#define fio()                     \
    ios_base::sync_with_stdio(0); \
    cin.tie(0)
using namespace std;
 
typedef long long ll;
typedef pair<intint> pii;
typedef pair<ll, ll> pll;
typedef tuple<intintint> tpi;
typedef tuple<ll, ll, ll> tpl;
typedef pair<double, ll> pdl;
 
const int INF = 0x3f3f3f3f;
const ll IINF = 0x3f3f3f3f3f3f3f3f;
const int dx[] = { 010-1 };
const int dy[] = { 10-10 };
 
vector<int> g[1010101];
int dp[1010101][2], depth[1010101];
 
int f(int x, int k, int lev){
    if(dp[x][k] != -1return dp[x][k];
 
    dp[x][k] = k;
    depth[x] = lev;
    if(k == 1){
        for(auto nx : g[x]){
            if(depth[nx] > lev) dp[x][k] += min(f(nx, 0, lev+1), f(nx, 1, lev+1));
        }
    }
    else{
        for(auto nx : g[x]){
            if(depth[nx] > lev) dp[x][k] += f(nx, 1, lev+1);
        }
    }
    return dp[x][k];
}
 
int main(){
    memset(dp, -1sizeof(dp));
    memset(depth, INF, sizeof(depth));
    int n; scanf("%d"&n);
    for(int i = 0; i < n-1; i++){
        int u, v; scanf("%d %d"&u, &v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    printf("%d", min(f(101), f(111)));
}
 
cs

 

<회고>

트리는 트리로 만들어져 있다는 최적 부분 구조를 이용해볼 수 있는 문제였다.