Skip to content

Commit cac0a62

Browse files
authored
Merge pull request #71 from chaesc1/chaesc1
행성터널 MST - Kruskal
2 parents c12b36b + 34260a5 commit cac0a62

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package week7.Day0904.BOJ행성터널;
2+
3+
import java.io.BufferedReader;
4+
import java.io.InputStreamReader;
5+
import java.util.ArrayList;
6+
import java.util.Collections;
7+
import java.util.StringTokenizer;
8+
9+
public class BOJ2887 {
10+
static class Planet {
11+
int id;
12+
int x;
13+
int y;
14+
int z;
15+
16+
public Planet(int id, int x, int y, int z) {
17+
this.id = id;
18+
this.x = x;
19+
this.y = y;
20+
this.z = z;
21+
}
22+
}
23+
24+
static class Node implements Comparable<Node> {
25+
int u, v;
26+
int cost;
27+
28+
public Node(int u, int v, int cost) {
29+
// 연결된 두 행성
30+
this.u = u;
31+
this.v = v;
32+
this.cost = cost;
33+
}
34+
35+
@Override
36+
public int compareTo(Node o) {
37+
return this.cost - o.cost;
38+
}
39+
}
40+
41+
static ArrayList<Planet> planetList;
42+
static ArrayList<Node> nodeList;
43+
static int[] parent;
44+
static int N;
45+
46+
public static void main(String[] args) throws Exception {
47+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
48+
StringTokenizer st;
49+
50+
N = Integer.parseInt(br.readLine());
51+
planetList = new ArrayList<>();
52+
nodeList = new ArrayList<>();
53+
54+
for (int i = 0; i < N; i++) {
55+
st = new StringTokenizer(br.readLine(), " ");
56+
planetList.add(new Planet(i, Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())));
57+
}
58+
59+
// 두 행성 A(xA, yA, zA)와 B(xB, yB, zB)를 터널로 연결할 때 드는 비용은 min(|xA-xB|, |yA-yB|, |zA-zB|)
60+
61+
// 각 좌표별로 정렬 후 인접한 행성들 사이의 비용을 계산하여 엣지 리스트에 추가
62+
planetList.sort((a, b) -> a.x - b.x);
63+
for (int i = 1; i < N; i++) {
64+
int cost = Math.abs(planetList.get(i).x - planetList.get(i - 1).x);
65+
nodeList.add(new Node(planetList.get(i - 1).id, planetList.get(i).id, cost));
66+
}
67+
68+
planetList.sort((a, b) -> a.y - b.y);
69+
for (int i = 1; i < N; i++) {
70+
int cost = Math.abs(planetList.get(i).y - planetList.get(i - 1).y);
71+
nodeList.add(new Node(planetList.get(i - 1).id, planetList.get(i).id, cost));
72+
}
73+
74+
planetList.sort((a, b) -> a.z - b.z);
75+
for (int i = 1; i < N; i++) {
76+
int cost = Math.abs(planetList.get(i).z - planetList.get(i - 1).z);
77+
nodeList.add(new Node(planetList.get(i - 1).id, planetList.get(i).id, cost));
78+
}
79+
80+
// 크루스칼 알고리즘을 적용하기 위해 엣지 리스트를 정렬
81+
Collections.sort(nodeList);
82+
83+
// makeSet()
84+
// Union-Find 자료구조 초기화
85+
parent = new int[N];
86+
for (int i = 0; i < N; i++) {
87+
parent[i] = i;
88+
}
89+
// 최소비용 조합
90+
int result = 0;
91+
int totalEdges = 0;
92+
93+
for (Node node : nodeList) {
94+
// 두 행성이 서로 다른 집합에 존재한다면 합치기
95+
if (find(node.u) != find(node.v)) {
96+
union(node.u, node.v);
97+
result += node.cost;
98+
totalEdges++;
99+
if (totalEdges == N - 1) {
100+
break;
101+
}
102+
}
103+
}
104+
105+
System.out.println(result);
106+
}
107+
108+
// 경로 압축 기법을 사용하여 부모노드 찾기
109+
private static int find(int x) {
110+
if (parent[x] == x) {
111+
return x;
112+
}
113+
return parent[x] = find(parent[x]);
114+
}
115+
116+
// 두 집합을 합치기
117+
private static void union(int x, int y) {
118+
int rootA = find(x);
119+
int rootB = find(y);
120+
if (rootA != rootB) {
121+
parent[rootB] = rootA;
122+
}
123+
}
124+
}

0 commit comments

Comments
 (0)