티스토리 뷰
728x90
문제 링크
2887번: 행성 터널
첫째 줄에 행성의 개수 N이 주어진다. (1 ≤ N ≤ 100,000) 다음 N개 줄에는 각 행성의 x, y, z좌표가 주어진다. 좌표는 -109보다 크거나 같고, 109보다 작거나 같은 정수이다. 한 위치에 행성이 두 개 이
www.acmicpc.net
풀이
점이 10만 개입니다. 이론상 모든 점을 연결할 수 있으므로 완전 그래프 꼴이긴 합니다. 간선이 너무 많은 것만 빼면 전형적인 최소 스패닝 트리 문제입니다.
근데 잘 생각해보면 굳이 모든 간선을 볼 필요가 없습니다.
우리는 최소 스패닝 트리를 만들거니까 축별로 정렬 후 이웃한 점끼리만 간선을 맺어주면 됩니다.
이게 왜 되는지 그림으로 살펴봅시다.
어떤 한 축만 고려했을 때, a,b,c가 그림처럼 연속한 점이라고 하겠습니다.

최소 스패닝 트리를 만드는 과정에서 우선 a-b를 연결합니다.

다음으론 b-c를 연결합니다.

이렇게 되면 무슨일이 있어도 a와 c는 거리 3으로 연결되지 않습니다.
즉, 좌표순으로 이웃한 정점끼리의 간선만 고려해줘도 된다는 말입니다.
이 원리를 적용하면 결국 정점 하나당 최대 6개의 간선만 존재하게 됩니다.
적당한 크기의 그래프를 모델링했으니 최소 스패닝 트리를 쉽게 구할 수 있습니다.
정답 코드
#include <bits/stdc++.h> #define INF 0x3f3f3f3f3f3f3f3f #define ft first #define sd second #define all(x) (x).begin(), (x).end() using namespace std; using ll = long long; using pll = pair<ll, ll>; using vpll = vector<pll>; vpll p1, p2, p3; int n; int par[111'111]; int find(int x) { if (par[x] == -1) return x; return par[x] = find(par[x]); } struct Edge { int u, v; ll c; Edge(int u = 0, int v = 0, ll c = 0) : u(u), v(v), c(c) {} }; vector<Edge> p; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); memset(par, -1, sizeof(par)); cin >> n; for (int i = 0; i < n; i++) { ll x, y, z; cin >> x >> y >> z; p1.emplace_back(x, i); p2.emplace_back(y, i); p3.emplace_back(z, i); } sort(all(p1)); sort(all(p2)); sort(all(p3)); auto foo = [&](pll a, pll b) { int u = a.sd, v = b.sd; ll val = abs(a.ft - b.ft); p.emplace_back(u, v, val); }; for (int i = 1; i < n; i++) { foo(p1[i], p1[i - 1]); foo(p2[i], p2[i - 1]); foo(p3[i], p3[i - 1]); } sort(all(p), [&](const auto &a, const auto &b) { return a.c < b.c; }); ll ans = 0; for (const Edge &e: p) { auto[u, v, c] = e; u = find(u); v = find(v); if (u != v) { par[u] = v; ans += c; } } cout << ans; }
728x90
'알고리즘 > 문제 풀이' 카테고리의 다른 글
[BOJ] 백준 7579 앱 (1) | 2021.03.08 |
---|---|
[BOJ] 백준 7453 합이 0인 네 정수 (0) | 2021.03.08 |
[BOJ] 백준 2623 음악프로그램 (0) | 2021.03.08 |
[BOJ] 백준 2098 외판원 순회 (0) | 2021.03.08 |
[BOJ] 백준 2342 Dance Dance Revolution (0) | 2021.03.08 |