728x90
문제 21924
21924번: 도시 건설
첫 번째 줄에 건물의 개수 $N$ $(3 \le N \le 10^5 )$와 도로의 개수 $M$ $(2 \le M \le min( {N(N-1) \over 2}, 5×10^5)) $가 주어진다. 두 번째 줄 부터 $M + 1$줄까지 건물의 번호 $a$, $b$ $(1 \le a, b \le N, a ≠ b)$와 두
www.acmicpc.net
[ 문제 풀이 ]
모든 건물을 최소한의 비용으로 연결하는 문제이므로 크루스칼 알고리즘으로 풀면 됩니다. 크루스칼 알고리즘에 대한 자세한 설명은 아래 포스트를 참고해주세요 :)
[JAVA] 서로소 집합(Disjoint Sets)과 연산
최근 알고리즘 문제를 풀면서 최소 신장 트리 개념에 대해 공부하다가 알게 된 크루스칼 알고리즘에서 이용되는 서로소 집합과 연산에 대해 정리해보겠습니다. 일단, 서로소는 공통으로 포함하
jeinie-developer.tistory.com
절약 비용 = (모든 도로를 설치할 때 드는 비용) - (모든 건물을 연결하는 도로의 최소 비용) 이므로, 입력값에서 비용들을 모두 더한 후, 크루스칼 알고리즘을 이용한 비용을 빼면 됩니다.
모든 건물을 연결할 수 없을 때는 -1을 출력해야 하므로, 사이클이 만들어지지 않는 경우에 한해서 queue에서 뽑은 개수를 카운트하여 이 값이 N-1이 아닌 경우에 -1을 출력하게 하면 됩니다.
[ 코드 ]
import java.io.*;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Main {
private static class Edge implements Comparable<Edge> {
int start, end, cost;
public Edge(int start, int end, int cost) {
this.start = start;
this.end = end;
this.cost = cost;
}
@Override
public int compareTo(Edge e) {
return this.cost - e.cost;
}
}
private static int N, M;
private static int[] parents;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
PriorityQueue<Edge> pq = new PriorityQueue<>();
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
parents = new int[N+1];
long totalCost = 0;
long minimumCost = 0;
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int start = Integer.parseInt(st.nextToken());
int end = Integer.parseInt(st.nextToken());
int cost = Integer.parseInt(st.nextToken());
pq.offer(new Edge(start, end, cost));
totalCost += cost;
}
makeSet();
int cnt = 0; // 뽑힌 개수
while (!pq.isEmpty()) {
Edge e = pq.poll();
int x = findParent(e.start);
int y = findParent(e.end);
if (x == y) continue;
union(x, y);
minimumCost += e.cost;
cnt++;
}
if (cnt != N-1) {
bw.write(String.valueOf(-1));
} else {
bw.write(String.valueOf(totalCost - minimumCost));
}
bw.flush();
}
private static void makeSet() {
for (int i = 1; i <= N; i++) {
parents[i] = i;
}
}
private static int findParent(int x) {
if (x == parents[x]) return x;
else return findParent(parents[x]);
}
private static void union(int x, int y) {
if (x > y) parents[x] = parents[y];
else parents[y] = parents[x];
}
}
728x90
'Algorithm > Baekjoon' 카테고리의 다른 글
[Baekjoon] 백준 1388번: 바닥장식 (JAVA) (1) | 2023.10.20 |
---|---|
[Baekjoon] 백준 13417번: 카드 문자열 (JAVA) (0) | 2023.10.18 |
[Baekjoon] 백준 14567번: 선수과목 (JAVA) (0) | 2023.10.14 |
[Baekjoon] 백준 11085번: 군사 이동 (JAVA) (0) | 2023.10.12 |
[Baekjoon] 백준 11123번: 양 한마리... 양 두마리... (JAVA) (2) | 2023.10.11 |