반응형

문제 링크: https://www.acmicpc.net/problem/9938

 

9938번: 방 청소

문제 은기는 술병 N개(1부터 N까지 번호가 매겨져 있다)와 서랍 L개(1부터 L까지 번호가 매겨져 있다)를 가지고 있다. 술병은 은기의 방 바닥에 흩어져 있고, 어린이날을 맞이해 방 청소를 하려고 한다.  서랍에는 술병이 하나 들어갈 수 있다. 나중에 원하는 술을 빠르게 찾을 수 있게 하기 위해 은기는 각각의 술병이 들어갈 수 있는 서랍의 번호 Ai와 Bi를 공책에 적어 놓았다. 은기는 술병을 1번부터 N번까지 순서대로 정리할 것이고, 각각의 술병에 대

www.acmicpc.net

<문제 풀이> Union-Find(유니온-파인드), Disjoint-Set(서로소집합)

 

 

각 병에 대해서 A서랍, B서랍을 노드로 생각하고 그래프를 만듭니다. 여기서 부모 노드를 비어있는 서랍, 자식 노드를 병이 들어가 있는 서랍이라고 하면 그래프로 쉽게 문제를 해결할 수 있습니다.

 

서랍에 병을 넣을 때마다 넣었는지 여부를 체크해줍니다.

 

1. 서랍 A가 비어있다면 A를 자식 노드로 하고 B를 부모 노드로 한다. 

 

2. 서랍 B가 비어있다면 B를 자식 노드로 하고 A를 부모 노드로 한다.

 

3. 서랍 A에 부모 노드가 방문이 안됐으면(병을 옮길 수 있으면) 서랍 A에 부모 노드를 자식 노드로 하고 B를 부모 노드로 한다.

 

4. 서랍 B에 부모 노드가 방문이 안됐으면(병을 옮길 수 있으면) 서랍 B에 부모 노드를 자식 노드로 하고 A를 부모 노드로 한다.

 

서랍에 병이 들어있을 때 병을 다른 서랍으로 옮기는 과정들을 Union 연산으로 한 그래프를 만든다고 생각하고 빈 서랍을 찾는 데는 Find 연산으로 부모 노드를 찾는다고 생각하면 됩니다.

 

 

 

<C++ 소스 코드>

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
#include <iostream>
using namespace std;
 
int node[300001];
bool visited[300001];
 
int Find(int x) {
    if (x == node[x]) return x;
    return node[x] = Find(node[x]);
}
 
void Union(int x, int y) {
    int xParents = Find(x);
    int yParents = Find(y);
    node[xParents] = yParents;
}
 
int main(void) {
    ios::ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int N, L;
    
    cin >> N >> L;
    
    for (int i = 1; i <= L; i++) {
        node[i] = i;
    }
 
    while (N--) {
        int a, b;
        cin >> a >> b;
        if (!visited[a]) {
            visited[a] = true;
            Union(a, b); //a의 부모를 b로
            cout << "LADICA\n";
        }
        else if (!visited[b]) {
            visited[b] = true;
            Union(b, a); //b의 부모를 a로
            cout << "LADICA\n";
        }
        else if (!visited[Find(node[a])]) {
            visited[Find(node[a])] = true
            Union(a, b); //a의 부모를 b로
            cout << "LADICA\n";
        }
        else if (!visited[Find(node[b])]) {
            visited[Find(node[b])] = true;
            Union(b, a); //b의 부모를 a로
            cout << "LADICA\n";
        }
        else {
            cout << "SMECE\n";
        }
    }
 
    return 0;
}
cs

 

반응형

+ Recent posts