Algorithm/BOJ

[BOJ] 행성 터널

goakgoak 2020. 11. 28. 17:20

[2887] 행성 터널

www.acmicpc.net/problem/2887

 

Solution

  • 행성들을 잇는 최소 간선 트리를 만드는 간단한 문제이다.
  • 처음에는 행성을 이을 수 있는 모든 간선을 미리 구해서 푸는 방식으로 접근했는 데 메모리 초과로 틀렸다.
  • int x, y, z -> 12byte이고,  행성 개수가 최대 10만개이기 때문에 (10만 * 10만 / 2) = 약 50억으로 12byte * 50억이라하면 메모리가 초과될 수 밖에 없었다.
  • 문제를 다시 한 번 살펴보면 행성의 x, y, z 좌표를 각각 비교해서 최소 비용을 구하는 것이므로 모든 행성간의 비용을 계산할 필요 없이 좌표 별로 오름차순으로 정렬한 뒤 바로 옆 행성만 비교하면 된다.
  • 예를들어 행성 A, B, C의 x좌표를 기준으로 정렬한 결과가 B(3) - A(5) - C(9)라고 하면 바로 옆에 있는 행성과의 거리가 가장 적기 때문에 B-A, A-C 만 pq에 저장하면된다.

 

 

소스코드

 

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
117
118
119
120
121
122
123
124
125
126
127
128
129
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
 
public class Main {
    static int n;
    static int[] p;
    static List<Node> list;
 
    static class Edge implements Comparable<Edge> {
        private int start;
        private int end;
        private int val;
 
        public Edge(int start, int end, int val) {
            this.start = start;
            this.end = end;
            this.val = val;
        }
 
        @Override
        public int compareTo(Edge o) {
            return this.val - o.val;
        }
    }
 
    static class Node {
        private int x;
        private int y;
        private int z;
        private int num;
 
        public Node(int x, int y, int z, int num) {
            this.x = x;
            this.y = y;
            this.z = z;
            this.num = num;
        }
    }
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = stoi(br.readLine());
 
        p = new int[n];
        for (int i = 0; i < n; i++) {
            p[i] = i;
        }
 
        list = new ArrayList<>();
        int x, y, z;
        StringTokenizer st;
        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
            x = stoi(st.nextToken());
            y = stoi(st.nextToken());
            z = stoi(st.nextToken());
 
            list.add(new Node(x, y, z, i));
        }
 
        PriorityQueue<Edge> pq = new PriorityQueue<>();
        Collections.sort(list, new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {
                return o1.x - o2.x;
            }
        });
        for (int i = 0; i < list.size() - 1; i++) {
            pq.add(new Edge(list.get(i).num, list.get(i + 1).num, Math.abs(list.get(i).x - list.get(i + 1).x)));
        }
 
        Collections.sort(list, new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {
                return o1.y - o2.y;
            }
        });
        for (int i = 0; i < list.size() - 1; i++) {
            pq.add(new Edge(list.get(i).num, list.get(i + 1).num,Math.abs(list.get(i).y - list.get(i + 1).y)));
        }
 
        Collections.sort(list, new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {
                return o1.z - o2.z;
            }
        });
        for (int i = 0; i < list.size() - 1; i++) {
            pq.add(new Edge(list.get(i).num, list.get(i + 1).num, Math.abs(list.get(i).z - list.get(i + 1).z)));
        }
 
        int answer = 0;
        int count = 0;
        while (!pq.isEmpty()) {
            Edge edge = pq.poll();
            if (find(edge.start) != find(edge.end)) {
                union(edge.start, edge.end);
                answer += edge.val;
                count++;
            }
            if (count == n - 1) {
                break;
            }
        }
 
        System.out.println(answer);
    }
 
    private static void union(int a, int b) {
        a = find(a);
        b = find(b);
        if (a != b) {
            p[b] = a;
        }
    }
 
    private static int find(int a) {
        if (p[a] == a) {
            return a;
        }
        return p[a] = find(p[a]);
    }
 
    private static int stoi(String s) {
        return Integer.parseInt(s);
    }
}
cs