반응형
    
    
    
  문제 출처 :
https://www.acmicpc.net/problem/9938
알고리즘 분석 :
문제 해결에 필요한 사항
1. Union Find :: http://www.crocus.co.kr/683
[4195번] 친구 네트워크 :: http://www.crocus.co.kr/686 이 문제를 푼 사람이라면 방 청소 문제는 쉽게 접근 할 수 있을 것이고,
친구 네트워크 문제를 풀어보지 않았다면 방 청소 문제 다음 저 문제를 풀어보는 것을 추천한다.
이 문제는 각 서랍에 술병이 1개만 있어야하고, 그 술병을 어떻게 옮겨가며 최종적으로 마실지 혹은 안마시고 보관할지 결정해야 한다.
이 문제를 접근하기 위한 몇가지 생각이 든다.
유니온 파인드로 인해 일단 노드들이 뭉쳐지는 생각은 해 볼 수 있다.
하지만 이걸 노드간에 이동하면서 술을 옮긴다.. 이건 매우 시간 복잡도면에서도 무너질 가능성이 높고 구현 자체도 까다로워 보인다.
따라서 이 문제를 그냥 단순하게 생각해보자.
유니온 파인드로 뭉쳐진 트리는 k개의 노드를 가지고 있을 것이다. 이때 k개의 노드수 자체가 보관 할 수 있는 개수를 의미한다.
따라서 술병이 매번 들어올 때 마다 그 해당하는 트리의 루트 노드가 보관 가능 개수를 컨트롤 해주면 된다.
하나 들어오면 -1, 만약 트리가 합쳐지는 과정이면 a트리의 노드 개수 + b트리의 노드 개수 -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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93  | #include <iostream> #include <cstdio> #include <string> #define swap(a,b){int t = a; a = b; b = t;} using namespace std; typedef pair<int, int> pii; int node; // first :: 부모 표현 second :: 자신을 포함한 자식 노드 개수 표현 pii parent[300001]; int level[300001]; int find(int u) {     // 루트 노드이면 return u     if (u == parent[u].first)         return u;     // 그 외에는 자신의 루트를 찾으러 간다.     return parent[u].first = find(parent[u].first); } void merge(int u, int v) {     u = find(u);     v = find(v);     // 루트가 같다면 이미 같은 트리     if (u == v)     {         if (parent[v].second - 1 < 0)             printf("SMECE\n");         else         {             parent[v].second--;             printf("LADICA\n");         }         return;     }     // u가 v보다 더 깊은 트리라면 swap     if (level[u] > level[v])         swap(u, v); // 항상 u가 더 작은 트리가 되도록 한다.      // u의 루트가 v가 되도록     parent[u].first = v;     // u와 v의 깊이가 같을 때 v의 깊이를 늘려준다.     if (level[u] == level[v])         ++level[v];     // 루트 노드에는 항상 아래 노드의 총 합 개수를 저장해준다고 생각하면     if (parent[v].second + parent[u].second - 1 < 0)         printf("SMECE\n");     else     {         parent[v].second += parent[u].second - 1;         printf("LADICA\n");     } } int main() {     int n, m;     scanf("%d %d", &n, &m);     // 초기화     for (int i = 1; i <= m; i++)     {         parent[i].first = i;         parent[i].second = 1;         level[i] = 1;     }     while (n--)     {         int s1, s2;         scanf("%d %d", &s1, &s2);         merge(s1, s2);     }     return 0; } //                                                       This source code Copyright belongs to Crocus //                                                        If you want to see more? click here >>  | Crocus | 
반응형
    
    
    
  'Applied > 알고리즘 문제풀이' 카테고리의 다른 글
| [10775번] 공항 (0) | 2017.03.23 | 
|---|---|
| [2133번] 타일 채우기 (4) | 2017.03.23 | 
| [4195번] 친구 네트워크 (4) | 2017.03.23 | 
| [1976번] 여행 가자 (0) | 2017.03.23 | 
| [1717번] 집합의 표현 (2) | 2017.03.23 |