[BOJ 1922, Java] 网络连接
BOJ 1922,“网络连接”题的 Java 解法
题目链接
分类
图论,最小生成树
说明
引言
最近只顾着做题,感觉对理论有些疏忽,因此想在记录解题过程的同时,哪怕只是简单地梳理一下理论。
MST(minimum spanning tree,最小生成树)
- 什么是生成树?
指包含图中所有顶点的树。
- 最小生成树
指在所有生成树中总边长最短的那棵
- 主要特征
包含 n 个顶点,且拥有 (n - 1) 条边 由于边长最小,因此可用于企业内部网络构建等场景
普雷姆算法
-
选择 1 个初始顶点
-
从MST中包含的顶点所连接的边中,依次选择最短的边
-
当所有顶点均被连接时结束
克鲁斯卡尔算法
-
按权重对所有边进行排序
-
在不形成环的情况下,依次添加边
-
当所有顶点均被连接时结束
解题代码
import java.io.*;
import java.util.*;
public class Main {
// 간선 정보 클래스 선언
public static class Connection implements Comparable<Connection> {
private final int cost;
private final int start;
private final int end;
public Connection(int cost, int start, int end) {
this.cost = cost;
this.start = start;
this.end = end;
}
// 가중치를 통한 비교
public int compareTo(Connection other) {
return this.cost - other.cost;
}
}
// 정점의 집합을 확인하는 함수
public static int checkUnion(int[] unionInfo, int targetVertex) {
if (unionInfo[targetVertex] != targetVertex) {
unionInfo[targetVertex] = checkUnion(unionInfo, unionInfo[targetVertex]);
}
return unionInfo[targetVertex];
}
// 정점 2개가 집합을 이루는지 확인하는 함수
public static boolean isUnion(int[] unionInfo, int vertex1, int vertex2) {
return checkUnion(unionInfo, vertex1) == checkUnion(unionInfo, vertex2);
}
// 집합을 합쳐주는 함수
public static void makeUnion(int[] unionInfo, int vertex1, int vertex2) {
int group1 = checkUnion(unionInfo, vertex1);
int group2 = checkUnion(unionInfo, vertex2);
if (group2 > group1) {
unionInfo[group2] = group1;
} else {
unionInfo[group1] = group2;
}
}
public static void main(String[] args) throws IOException {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(System.out));
// 정점 및 간선의 갯수 입력
int vertexNumber = Integer.parseInt(input.readLine());
int edgeNumber = Integer.parseInt(input.readLine());
// 간선 정보를 담을 우선순위 큐 선언
PriorityQueue<Connection> costPriorityQueue = new PriorityQueue<>();
// 간선 정보 입력
for (int i = 0; i < edgeNumber; i++) {
StringTokenizer connectionInfo = new StringTokenizer(input.readLine(), "[ ]");
int startNode = Integer.parseInt(connectionInfo.nextToken());
int endNode = Integer.parseInt(connectionInfo.nextToken());
int cost = Integer.parseInt(connectionInfo.nextToken());
Connection connection = new Connection(cost, startNode, endNode);
costPriorityQueue.add(connection);
}
// 집합에 포함된 정점의 갯수와 최소 가중치 정보를 담을 변수 선언
int totalCost = 0;
int totalEdge = 0;
// 집합 정보를 담을 배열 선언
int[] groupInfo = new int[vertexNumber + 1];
for (int i = 0; i < vertexNumber + 1; i++) {
groupInfo[i] = i;
}
// Kruskal's Algorithm
while (totalEdge < vertexNumber - 1 && !costPriorityQueue.isEmpty()) {
// 가중치 순으로 확인
Connection nowConnection = costPriorityQueue.poll();
// 집합 관계를 확인하여 아직 집합이 아닌 경우 집합에 추가하고 가중치 가산
if (!isUnion(groupInfo, nowConnection.start, nowConnection.end)) {
makeUnion(groupInfo, nowConnection.start, nowConnection.end);
totalEdge += 1;
totalCost += nowConnection.cost;
}
}
// 최종 최소 가중치값 출력
output.write(Integer.toString(totalCost));
output.flush();
output.close();
}
}
댓글 작성
게시글에 대한 의견을 남겨 주세요.