반응형

문제 출처 :


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



알고리즘 분석 :


문제 해결에 필요한 사항

1. 유니온 파인드(Union Find) :: http://www.crocus.co.kr/683

2. 최소 스패닝 트리(MST) :: http://www.crocus.co.kr/733


이 문제는 문제 내용에서 힌트를 얻어야 해결 할 수 있다.


현재 각 정점간의 최단 거리를 min(|xA-xB|, |yA-yB|, |zA-zB|)로 정의하고있다.


즉, 최소 스패닝 트리로 접근 하기위해 x,y,z로 이루어진 idx들을 이용하여 정점들을 연결해주면 된다.


이때 min방식을 어떻게 이용할 것이냐면


x에 대해 정렬을 해주면 idx가 이리저리 섞일 것이고

그 인접한 x끼리 거리를 구해 거리와 idx를 pq에 넣어준다.


y도 y에 대해 정렬을 해주면 idx가 이리저리 섞일 것이고

그 인접한 y끼리 거리를 구해 거리와 idx를 pq에 넣어준다.

마지막으로 z에 대해 정렬을 해주면 idx가 이리저리 섞일 것이고

그 인접한 z끼리 거리를 구해 거리와 idx를 pq에 넣어준다.


이렇게되면 pq에는 가장 짧은 거리부터 idx들이 나타날 것이다.


결국 이 방식으로 행성을 연결해주면 최소 스패닝 트리를 이루는 행성을 만들 수 있다.





소스 코드 : 


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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
 
using namespace std;
 
typedef pair<intint> pii;
 
typedef struct _INFO_
{
    int x;
    int y;
    int z;
    int idx;
}INFO;
 
INFO info[100001];
int parent[100001];
long long ans;
bool chk;
 
bool compx(const INFO &a, const INFO &b)
{
    return a.x < b.x;
}
bool compy(const INFO &a, const INFO &b)
{
    return a.y < b.y;
}
bool compz(const INFO &a, const INFO &b)
{
    return a.z < b.z;
}
 
int find(int u)
{
    if (u == parent[u])
        return u;
 
    return parent[u] = find(parent[u]);
}
 
void merge(int u, int v)
{
    chk = false;
    u = find(u);
    v = find(v);
 
    if (u == v)
        return;
 
    parent[u] = v;
    chk = true;
}
 
int main()
{
    int n;
 
    scanf("%d"&n);
 
    for (int i = 0; i < n; i++)
        parent[i] = i;
 
    // 정보 입력
    for (int i = 0; i < n; i++)
    {
        scanf("%d %d %d"&info[i].x, &info[i].y, &info[i].z);
        info[i].idx = i;
    }
 
    priority_queue<pair<int, pair<intint>>> pq;
 
    // x에 대해 정렬하여 인접한 x끼리 길이를 구해 pq에 push한다.
    sort(info, info + n, compx);
    for (int i = 1; i < n; i++)
        pq.push({ -abs(info[i].x - info[i - 1].x), pii(info[i].idx, info[i - 1].idx) });
 
    // y에 대해 정렬하여 인접한 y끼리 길이를 구해 pq에 push한다.
    sort(info, info + n, compy);
    for (int i = 1; i < n; i++)
        pq.push({ -abs(info[i].y - info[i - 1].y), pii(info[i].idx, info[i - 1].idx) });
 
    // z에 대해 정렬하여 인접한 z끼리 길이를 구해 pq에 push한다.
    sort(info, info + n, compz);
    for (int i = 1; i < n; i++)
        pq.push({ -abs(info[i].z - info[i - 1].z), pii(info[i].idx, info[i - 1].idx) });
 
    // 위에서 구한 과정으로 작은 값 순서로 idx를 서로 merge해준다.
    while (!pq.empty())
    {
        int val = -pq.top().first;
        int idx1 = pq.top().second.first;
        int idx2 = pq.top().second.second;
 
        pq.pop();
        merge(idx1, idx2);
 
        // merge가 성공하면
        if (chk)
            ans += val;
    }
 
    printf("%lld", ans);
    return 0;
}
 
//                                                       This source code Copyright belongs to Crocus
//                                                        If you want to see more? click here >>
Crocus


반응형

'Applied > 알고리즘 문제풀이' 카테고리의 다른 글

[4386번] Freckles  (0) 2017.04.05
[2211번] 네트워크 복구  (0) 2017.04.04
[6497번] Dark roads  (6) 2017.04.04
[1647번] 도시 분할 계획  (0) 2017.04.04
[4343번] Arctic Network  (0) 2017.04.04