中文
[BOJ 1922, Java] 网络连接

[BOJ 1922, Java] 网络连接

BOJ 1922,“网络连接”题的 Java 解法

题目链接

BOJ 1922

分类

图论,最小生成树

说明

引言

最近只顾着做题,感觉对理论有些疏忽,因此想在记录解题过程的同时,哪怕只是简单地梳理一下理论。

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();

    }

}

댓글 작성

게시글에 대한 의견을 남겨 주세요.

댓글 0