처음에 이 문제를 접했을 때, 사실 왜 gold 1이나 부여되어 있는지 몰랐는데 그대로 제출하니 메모리 초과가 발생하였다.
N이 10만개가 들어왔을 경우 내 알고리즘은 현재 N * (N-1)개 만큼의 간선정보를 저장하고 있다. 하지만, 이 문제는 모든 간선에 대한 정보를 알 필요 없이 x축, y축, z축에 대해 인접한 행성만 보면 된다. 그 이유는 백준 질문게시판에 나와있는 아래 내용과 같다.
주어진 그래프의 MST를 T라고 합시다. 인접하지 않은 정점 A, B가 T에서 간선으로 연결되어있다고 가정하죠. 일반성을 잃지 않고 A, B 사이에 연결된 간선 무게가 |A_x - B_x| 라고 하죠. x 축으로 A, B 사이에 있는 정점 C가 존재합니다 (A_x <= C_x <= B_x) 여기서 A, B를 연결하는 간선을 제거하고 A, C 와 C, B를 연결합니다 (이 그래프를 G라고 하죠) G는 N개의 간선으로 이루어져 있고, 연결되어있다는건 자명합니다. 그리고 총 무게 변화는 최대 -|A_x - B_x| + |A_x - C_x| + |C_x - B_x| = 0 입니다. 즉 G의 싸이클에서 간선 아무거나 지워도 T보다 총 무게가 더 작습니다. T가 MST라는 가정이 모순되니 MST에서 연결된 정점은 인접합니다. |
코드
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
112
113
114
115
116
|
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int N;
typedef long long ll;
typedef struct coor
{
ll x,y,z;
int idx;
}coor;
typedef struct graph
{
int v1, v2;
ll cost;
}graph;
vector<coor> v;
vector<graph> g;
int getRoot(vector<int> &parent, int idx)
{
if (parent[idx] == idx) return idx;
else return parent[idx] = getRoot(parent, parent[idx]);
}
void merge(vector<int> &parent, int a, int b)
{
a = getRoot(parent, a); b = getRoot(parent, b);
if (a == b) return;
else if (a < b) parent[b] = a;
else parent[a] = b;
}
bool comp(graph a, graph b)
{
return a.cost < b.cost;
}
bool compX(coor a, coor b)
{
return a.x < b.x;
}
bool compY(coor a, coor b)
{
return a.y < b.y;
}
bool compZ(coor a, coor b)
{
return a.z < b.z;
}
int main()
{
cin.tie(NULL);
ios_base::sync_with_stdio(false);
cin >> N;
for(int i=0; i<N; i++)
{
coor c;
cin >> c.x >> c.y >> c.z;
c.idx = i + 1;
v.push_back(c);
}
sort(v.begin(), v.end(), compX);
for(int i=1; i<N; i++)
{
long long dist = min(min(abs(v[i-1].x - v[i].x), abs(v[i-1].y - v[i].y)), abs(v[i-1].z - v[i].z));
graph tmp;
tmp.v1 = v[i-1].idx;
tmp.v2 = v[i].idx;
tmp.cost = dist;
g.push_back(tmp);
}
sort(v.begin(), v.end(), compY);
for(int i=1; i<N; i++)
{
long long dist = min(min(abs(v[i-1].x - v[i].x), abs(v[i-1].y - v[i].y)), abs(v[i-1].z - v[i].z));
graph tmp;
tmp.v1 = v[i-1].idx;
tmp.v2 = v[i].idx;
tmp.cost = dist;
g.push_back(tmp);
}
sort(v.begin(), v.end(), compZ);
for(int i=1; i<N; i++)
{
long long dist = min(min(abs(v[i-1].x - v[i].x), abs(v[i-1].y - v[i].y)), abs(v[i-1].z - v[i].z));
graph tmp;
tmp.v1 = v[i-1].idx;
tmp.v2 = v[i].idx;
tmp.cost = dist;
g.push_back(tmp);
}
sort(g.begin(), g.end(), comp);
long long sum = 0;
vector<int> parent(N + 1);
for(int i=1; i<=N; i++)
parent[i] = i;
for(int i=0; i<g.size(); i++)
{
int v1 = g[i].v1; int v2 = g[i].v2;
if (getRoot(parent, v1) != getRoot(parent, v2))
{
merge(parent, v1, v2);
sum += g[i].cost;
}
}
cout << sum << "\n";
return (0);
}
|
cs |
위 코드와 같이 X, Y, Z축에 대해 각각 정렬한 뒤 인접한 행성들의 간선들을 모두 g에 저장한다. 그러면 6 * N개 만큼의 정보가 저장되어 있으므로 간선의 개수가 확연히 줄은 것을 알 수 있다.
이에 대해 크루스칼 알고리즘을 적용하면 쉽게 답을 구할 수 있다.
'Study > BOJ' 카테고리의 다른 글
BOJ - 구슬 탈출 2(13460) (0) | 2021.04.21 |
---|---|
BOJ - 어른 상어(19237) (0) | 2021.04.21 |
BOJ - 다리 만들기 2(17472) (0) | 2021.04.15 |
BOJ - 네트워크 연결(1922) (0) | 2021.04.15 |
BOJ - 거짓말(1043) (0) | 2021.04.14 |