ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 2533번 사회망서비스
    문제 풀이 2020. 3. 31. 21:31

    2533 사회망 서비스


    문제


    페이스북, 트위터, 카카오톡과 같은 사회망 서비스(SNS)가 널리 사용됨에 따라, 사회망을 통하여 사람들이 어떻게 새로운 아이디어를 받아들이게 되는가를 이해하는 문제가 중요해졌다. 사회망에서 사람들의 친구 관계는 그래프로 표현할 수 있는데,  이 그래프에서 사람은 정점으로 표현되고, 두 정점을 잇는 에지는 두 정점으로 표현되는 두 사람이 서로 친구 관계임을 표현한다. 

    예를 들어, 철수와 영희, 철수와 만수, 영희와 순희가 서로 친구 관계라면 이를 표현하는 친구 관계 그래프는 다음과 같다. 

    친구 관계 그래프를 이용하면 사회망 서비스에서 어떤 새로운 아이디어가 전파되는 과정을 이해하는데 도움을 줄 수 있다. 어떤 새로운 아이디어를 먼저 받아들인 사람을 얼리 아답터(early adaptor)라고 하는데, 사회망 서비스에 속한 사람들은 얼리 아답터이거나 얼리 아답터가 아니다. 얼리 아답터가 아닌 사람들은 자신의 모든 친구들이 얼리 아답터일 때만 이 아이디어를 받아들인다. 

    어떤 아이디어를 사회망 서비스에서 퍼뜨리고자 할 때, 가능한 한 최소의 수의 얼리 아답터를 확보하여 모든 사람이 이 아이디어를 받아들이게 하는  문제는 매우 중요하다. 

    일반적인 그래프에서 이 문제를 푸는 것이 매우 어렵다는 것이 알려져 있기 때문에, 친구 관계 그래프가 트리인 경우, 즉 모든 두 정점 사이에 이들을 잇는 경로가 존재하면서 사이클이 존재하지 않는 경우만 고려한다.

    친구 관계 트리가 주어졌을 때, 모든 개인이 새로운 아이디어를 수용하기 위하여 필요한 최소 얼리 어답터의 수를 구하는 프로그램을 작성하시오.


    입력


    첫 번째 줄에는 친구 관계 트리의 정점 개수 N이 주어진다. 단, 2 <= N <= 1,000,000이며, 각 정점은 1부터 N까지 일련번호로 표현된다. 두 번째 줄부터 N-1개의 줄에는 각 줄마다 친구 관계 트리의 에지 (u, v)를 나타내는 두 정수 u 와 v가 하나의 빈칸을 사이에 두고 주어진다. 


    출력


    주어진 친구 관계 그래프에서 아이디어를 전파하는데 필요한 얼리 아답터의 최소 수를 하나의 정수로 출력한다.




    풀이)

    재귀랑 dp를 합쳐서 푼 문제이다.


    과정을 보자면,

    1. 인접리스트를 이용해 친구 관계를 모두 표시한다.

    2. 1번부터 각 친구의 친구까지 재귀를 통해 방문한다.

    3. 조건을 이용해서 배열에 memoization해준다.

     (조건)

     본인이 얼리어답터가 아닐 시, 친구들은 모두 얼리어답터여만 한다.

     본인이 얼리어답터일 경우, 친구들이 얼리어답터이거나 얼리어답터가 아니다.


     dp[i][0] = 내가 얼리어답터일때, 친구들의 수의 합

     dp[i][1] = 내가 얼리어답터가 아닐때, 각 친구들이 얼리어답터거나 아닐 때 2가지 배열의 최솟값들의 합


    4. 1번 사람부터 memoization을 시작했으니, 1 ~ N번 사람까지의 정보가 1번 사람 dp에 합쳐서 저장되었을 것이다.

       dp[1][0]과 dp[1][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
    #include <stdio.h>
    #include <vector>
    #include <algorithm>
    using namespace std;
     
    int n;
    vector <int> vec[1000001];
    bool visited[1000001];
    int dp[1000001][2]; //0은 내가 얼리가 아닐때, 1은 내가 얼리일때
     
    void dfs(int idx) {
        visited[idx] = true;
        dp[idx][0= 0;
        dp[idx][1= 1;
        for (int i = 0; i < vec[idx].size(); i++) {
            if (visited[vec[idx][i]] == true)continue;
            dfs(vec[idx][i]);
            dp[idx][0+= dp[vec[idx][i]][1];//내가 얼리가 아니면, 내 친구들은 모두 얼리여야함
            dp[idx][1+= min(dp[vec[idx][i]][0], dp[vec[idx][i]][1]);//내가 얼리면, 내 친구들이 얼리 혹은 얼리가 아니여도됨
        }
    }
     
    int main() {
        scanf("%d"&n);
     
        for (int i = 0; i < n-1; i++) {
            int u, v;
            scanf("%d %d"&u, &v);
            vec[u].push_back(v);
            vec[v].push_back(u);
        }
        dfs(1);
        printf("%d", min(dp[1][0], dp[1][1]));
     
        return 0;
    }
    cs


    '문제 풀이' 카테고리의 다른 글

    [백준] 1182번 부분수열의 합  (0) 2020.04.01
    [백준] 1238번 파티  (0) 2020.03.31
    [백준] 1561번 놀이공원  (0) 2020.03.30
    [백준] 3079번 입국심사  (0) 2020.03.30
    [백준] 1939번 중량제한  (0) 2020.03.30

    댓글

Designed by Tistory.