Algorithm

[백준] 10423: 전기가 부족해 JAVA

하다보면 되겠지 2023. 2. 27. 00:17

접근

기본적으로는 크루스칼 알고리즘으로 푸는데, 이제 같은 트리라는 것만 확안하는 것이 아니라 한 트리 안에 발전소가 1개만 있어야 한다는 조건이 추가된다. 그래서 union을 할 때에는 루트값을 무조건 발전소가 있는 번호가 저장되도록 설정했고, find로 찾은 루트가 모두 발전소라면 넘어가도록 처리해주었다. 

 

그리고 모든 도시가 하나의 발전소에 연결되기 위해서 필요한 케이블의 개수는 n-k개이다. 설치된 케이블의 개수를 확인하여 n-k가 되면 while문을 종료하도록 했다. 

 

코드

package week7;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class BJ10423 {
    static class Edge implements Comparable<Edge> {
        int from, to, cost;

        public Edge(int from, int to, int cost) {
            this.from = from;
            this.to = to;
            this.cost = cost;
        }

        @Override
        public int compareTo(Edge o) {
            return this.cost - o.cost;
        }
    }

    static int[] root;
    static ArrayList<Integer> powerPlant;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = null;

        st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());
        int k = Integer.parseInt(st.nextToken());

        // 발전소가 설치된 도시의 번호
        powerPlant = new ArrayList<>();
        PriorityQueue<Edge> pq = new PriorityQueue<>();

        st = new StringTokenizer(br.readLine());
        while(st.hasMoreTokens()){
            int val = Integer.parseInt(st.nextToken());
            powerPlant.add(val);
        }

        for (int i = 0; i < m; i++) {
            st = new StringTokenizer(br.readLine());

            int u = Integer.parseInt(st.nextToken());
            int v = Integer.parseInt(st.nextToken());
            int w = Integer.parseInt(st.nextToken());
            pq.add(new Edge(u, v, w));
        }

        // 크루스칼 알고리즘
        root = new int[n+1];
        for (int i = 0; i <= n; i++)
            root[i] = i;

        int answer = 0;
        int cnt = 0;

        while(!pq.isEmpty()){
            if(cnt == n-k) break;

            Edge e = pq.poll();

            int r1 = find(e.from);
            int r2 = find(e.to);

            // 같은 트리 안에 있거나, 둘 다 발전소에 연결되어 있을 경우 넘어감
            if(r1 == r2 || (powerPlant.contains(r1) && powerPlant.contains(r2))) continue;

            union(r1, r2);
            answer += e.cost;
            cnt++;
        }

        System.out.println(answer);
    }

    static int find(int n){
        if(root[n] == n) return n;
        return root[n] = find(root[n]);
    }

    static void union(int r1, int r2){
        if(powerPlant.contains(r1)){
            int tmp = r1;
            r1 = r2;
            r2 = tmp;
        }

        root[r1] = r2;
    }
}