반응형
리뷰
다른 MST 문제와는 다르게 모든 간선을 구하는 것이 아닌 필요한 간선만 구해 MST를 구하는 문제
기존의 모든 간선을 구하는 방식을 사용했더니 바로 메모리 초과가 출력되었다.
https://www.acmicpc.net/problem/2887
문제 풀이
전역 변수
- n : 행성의 개수를 저장할 변수
- nodes : Union-Find를 통해 MST를 구할 노드의 배열, 노드의 최대 크기인 10만보다 1크게 설정해 준다.
- Pos : 행성의 각 축 좌표 위치 정보를 나타낼 구조체, sort가 필요하므로 compare함수를 작성해 준다.
- Edge : 행성간 간선의 정보를 나타낼 구조체, 마찬가지로 sort가 필요하다.
- PI : x, y, z축과 행성의 번호를 저장할 Pos타입 벡터
- n값을 입력 받고, 1 ~ n까지 행성 정보를 입력 받고, nodes배열을 초기화 해준다.
- 좌표를 입력 받을땐 PI의 0에는 x좌표, 1에는 y좌표, 2에는 z좌표를 행성 번호와 함께 push 해준다.
- PI의 0 ~ 2인덱스의 벡터를 각 좌표 기준으로 오름차순으로 정렬해 준다. (행성 번호가 뒤죽박죽 되는 것이 정상이다.)
- 간선 정보를 담을 Edge타입 벡터 edges를 초기화 해준다.
- x, y, z좌표를 기준으로 가장 인접한 두 행성간 거리의 정보와 행성 번호 정보를 edges에 push해준다.
- edges를 간선의 가중치를 기준으로 오름차순 정렬해 준다. 이후 Union-Find를 통해 MST를 구해주면 된다.
참고 사항
- 기존의 크루스칼을 사용하여 각 행성간 간선을 모두 구해준다면 100000*99999/2 크기가 되어 메모리 초과가 된다.
- 이를 방지하기 위해 행성을 좌표위치순으로 정렬하고 인접한 행성들 끼리의 거리만 구해준 뒤 비교하는 것이다.
정답 코드
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n, nodes[100001];
struct Pos {
int pos, idx;
bool operator<(const Pos& other) const {
return pos < other.pos;
}
};
struct Edge {
int w, n1, n2;
bool operator<(const Edge& other) const {
return w < other.w;
}
};
vector<Pos> PI[3];
int Find(int a) {
if (nodes[a] == a) return a;
return nodes[a] = Find(nodes[a]);
}
bool Union(int a, int b) {
int A = Find(a);
int B = Find(b);
if (A == B) return false;
nodes[B] = A;
return true;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
nodes[i] = i;
int x, y, z; cin >> x >> y >> z;
PI[0].push_back({ x, i });
PI[1].push_back({ y, i });
PI[2].push_back({ z, i });
}
for (int i = 0; i < 3; i++) sort(PI[i].begin(), PI[i].end());
vector<Edge> edges;
for (int i = 0; i < n - 1; i++) {
edges.push_back({ abs(PI[0][i].pos - PI[0][i + 1].pos), PI[0][i].idx, PI[0][i + 1].idx });
edges.push_back({ abs(PI[1][i].pos - PI[1][i + 1].pos), PI[1][i].idx, PI[1][i + 1].idx });
edges.push_back({ abs(PI[2][i].pos - PI[2][i + 1].pos), PI[2][i].idx, PI[2][i + 1].idx });
}
sort(edges.begin(), edges.end());
int sum = 0;
for (Edge edge:edges) {
int w = edge.w, n1 = edge.n1, n2 = edge.n2;
if (Union(n1, n2)) sum += w;
}
cout << sum;
}
728x90
반응형
'알고리즘 공부 > C++' 카테고리의 다른 글
[G5] 백준 15681번 트리와 쿼리 C++ DFS, 깊이 우선 탐색, 트리 (1) | 2024.09.20 |
---|---|
[G4] 백준 2239번 스도쿠 C++ 백트래킹, 구현 (0) | 2024.09.20 |
[G1] 백준 13460번 구슬 탈출 2 C++ BFS, 구현, 시뮬레이션, 너비 우선 탐색 (2) | 2024.09.18 |
[G2] 백준 16946번 벽 부수고 이동하기 4 C++ BFS, FloodFill, 너비 우선 탐색 (0) | 2024.09.17 |
[G5] 백준 2166번 다각형의 면적 C++ 기하학, 신발끈 공식, 슈메르카우스키의 공식 (2) | 2024.09.16 |