전력난 문제는 여러 도시와 이들을 연결하는 도로들이 주어졌을 때,
모든 도시가 연결된 상태를 유지하면서 불필요한 도로의 전력 소비를 줄여
절약할 수 있는 전력의 총합을 구하는 문제입니다.
입력:
출력:
문제의 핵심은 모든 도시를 연결하는 상태를 유지하면서,
불필요한 도로의 전력 소비를 제거하는 것입니다.
즉, 전체 도로 비용에서 MST를 구성하는 데 사용된 도로 비용을 빼면
절약 가능한 전력의 양을 구할 수 있습니다.
아이디어:
allSum
)과 MST 도로 비용(mstSum
)을 각각 구합니다. allSum - mstSum
으로 계산됩니다.알고리즘 선택:
입력 처리 및 초기화:
allSum
)을 누적합니다.최소 신장 트리(MST) 구성:
mstSum
을 구합니다.절약 가능한 전력 계산:
allSum
)에서 MST 구성 비용(mstSum
)을 빼면,import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Main {
private static StringTokenizer st;
private static StringBuilder sb = new StringBuilder();
private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
private static int N, M;
private static PriorityQueue<int[]> pq;
private static int[] parent;
private static int allSum;
public static void main(String[] args) throws IOException {
/*
* 문제의 핵심은 모든 도시를 연결하는 상태를 유지하면서,
* 불필요한 도로를 제거해 절약할 수 있는 전력의 총합을 구하는 것입니다.
* 전체 도로 비용에서 MST 구성에 사용된 비용을 빼면,
* 절약 가능한 전력의 양을 구할 수 있습니다.
* 여기서는 Kruskal 알고리즘과 Union-Find 자료구조를 활용했습니다.
*/
while (true) {
if (!isSetting()) break;
sb.append(allSum - getMstSum()).append("\n");
}
System.out.println(sb.toString());
}
private static int getMstSum() {
int sum = 0;
while (pq.size() > 0) {
int[] cur = pq.poll();
int from = cur[0];
int to = cur[1];
int val = cur[2];
if (find(from) != find(to)) {
union(from, to);
sum += val;
}
}
return sum;
}
private static int find(int num) {
if (num == parent[num]) return num;
return parent[num] = find(parent[num]);
}
private static void union(int num1, int num2) {
int parent1 = find(num1);
int parent2 = find(num2);
if (parent1 < parent2) {
parent[parent2] = parent1;
find(num2); // 경로 압축을 통한 최적화
} else {
parent[parent1] = parent2;
find(num1); // 경로 압축을 통한 최적화
}
}
private static boolean isSetting() throws IOException {
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
if (N == 0 && M == 0) return false; // 종료 조건
parent = new int[N];
for (int i = 0; i < N; i++) {
parent[i] = i;
}
pq = new PriorityQueue<>(Comparator.comparingInt(o -> o[2]));
allSum = 0;
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int from = Integer.parseInt(st.nextToken());
int to = Integer.parseInt(st.nextToken());
int val = Integer.parseInt(st.nextToken());
allSum += val;
pq.add(new int[]{from, to, val});
}
return true;
}
}
입력 처리 및 초기화:
allSum
)을 누적합니다.최소 신장 트리(MST) 구성:
mstSum
을 구합니다.절약 가능한 전력 계산:
allSum
)에서 MST 구성 비용(mstSum
)을 빼면,