문제

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

걸린 시간

- 실패

풀이

C++

#include <bits/stdc++.h>
#define INF 1e9
typedef long long ll;
typedef unsigned long long ull;
using namespace std;

int n, u, v;
int cache[2][1000001];
set<int> adj[1000001];

int dp(int early, int here){
    // 기저 사례
    if(adj[here].size() == 0){
        if(early) return 1;
        else return 0;
    }
    // 메모이제이션
    int& ret = cache[early][here];
    if(ret != -1) return ret;
    // 재귀 호출
    ret = 0;
    for(auto it = adj[here].begin(); it != adj[here].end(); it++){
        int next = *it;
        if(early) ret += min(dp(1, next), dp(0, next));
        else ret += dp(1, next);
    }
    if(early) ret += 1;
    return ret;
}

void makeTree(){
    queue<int> q;
    q.push(1);
    while(!q.empty()){
        int size = q.size();
        for(int i = 0; i < size; i++){
            int v = q.front();
            q.pop();
            for(auto it = adj[v].begin(); it != adj[v].end(); it++){
                int w = *it;
                adj[w].erase(adj[w].find(v));
                q.push(w);
            }
        }
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n;
    for(int i = 0; i < n-1; i++){
        cin >> u >> v;
        adj[u].insert(v);
        adj[v].insert(u);
    }
    memset(cache, -1, sizeof(cache));
    makeTree();
    cout << min(dp(0, 1), dp(1, 1));
    return 0;
}

친구관계는 항상 트리 구조로 주어지기 때문에 어느 정점에서 시작해도 트리 형태가 유지된다.

친구 관계가 주어지면 양방향으로 연결한 후, 한 정점을 루트 노드로 가정하고 트리의 진행 방향과 반대인 edge 를 모두 제거하면 얼리 어답터의 개수를 세기 위한 준비가 끝난다. (입력을 받으며 루트 노드를 찾는 방법도 있지만 구현이 번거로워진다.)

사람들의 상태는 얼리 어답터이거나 얼리 어답터가 아닐 수 있다. 자신의 상태에 따라 자신의 친구들의 상태를 두 가지 경우로 나눌 수 있는데, 첫 번째로 자신이 얼리어답터라면 이미 아이디어를 받아들인 상태이기 때문에 자신의 모든 친구들이 얼리어답터인지는 따져보지 않아도 된다. 즉, 얼리 어답터인 사람과 얼리 어답터가 아닌 사람 두 가지 경우가 모두 올 수 있다. 두 번째로 자신이 얼리어답터가 아니라면 아이디어를 받아들이기 위해서는 자신의 모든 친구들이 항상 얼리 어답터이어야만 한다.

이대로 완전탐색을 진행하면 시간초과가 발생한다. 사이클이 없을 뿐이지 내 친구가 다른 사람의 친구가 될 수 있기 때문이다. 여기서 발생한 중복을 제거하기 위해선 현재 상태트리의 정점을 쌍으로 최소 인원의 얼리어답터를 메모이제이션하면 된다.

'Baekjoon' 카테고리의 다른 글

Baekjoon 11967번 불켜기  (0) 2020.10.14
Baekjoon 7575번 바이러스  (0) 2020.10.14
Baekjoon 19952번 인성 문제 있어??  (0) 2020.10.13
Baekjoon 1799번 비숍  (0) 2020.10.11
Baekjoon 2098번 외판원 순회  (0) 2020.10.10

댓글