알고리즘 공부/탐욕알고리즘(Greedy)

[프로그래머스] 섬 연결하기 - *크루스칼알고리즘

kdhoooon 2021. 5. 30. 21:06

문제


n개의 섬 사이에 다리를 건설하는 비용(costs)이 주어질 때, 최소의 비용으로 모든 섬이 서로 통행 가능하도록 만들 때 필요한 최소 비용을 return 하도록 solution을 완성하세요.

다리를 여러 번 건너더라도, 도달할 수만 있으면 통행 가능하다고 봅니다. 예를 들어 A 섬과 B 섬 사이에 다리가 있고, B 섬과 C 섬 사이에 다리가 있으면 A 섬과 C 섬은 서로 통행 가능합니다.

 

 

제한사항

  • 섬의 개수 n은 1 이상 100 이하입니다.
  • costs의 길이는 ((n-1) * n) / 2이하입니다.
  • 임의의 i에 대해, costs[i][0] 와 costs[i] [1]에는 다리가 연결되는 두 섬의 번호가 들어있고, costs[i] [2]에는 이 두 섬을 연결하는 다리를 건설할 때 드는 비용입니다.
  • 같은 연결은 두 번 주어지지 않습니다. 또한 순서가 바뀌더라도 같은 연결로 봅니다. 즉 0과 1 사이를 연결하는 비용이 주어졌을 때, 1과 0의 비용이 주어지지 않습니다.
  • 모든 섬 사이의 다리 건설 비용이 주어지지 않습니다. 이 경우, 두 섬 사이의 건설이 불가능한 것으로 봅니다.
  • 연결할 수 없는 섬은 주어지지 않습니다.

 

 

 

풀이


Greedy 알고리즘을 활용한 크루스칼알고리즘을 이용하여 문제를 풀 수 있다.

https://conpulake.tistory.com/107

 

백준 1922 (네트워크)* - 크루스칼알고리즘(Union-Find 사용)

문제 도현이는 컴퓨터와 컴퓨터를 모두 연결하는 네트워크를 구축하려 한다. 하지만 아쉽게도 허브가 있지 않아 컴퓨터와 컴퓨터를 직접 연결하여야 한다. 그런데 모두가 자료를 공유하기 위해

conpulake.tistory.com

위 문제와 같은 방식으로 해결하면 된다.

 

Union-Find 알고리즘을 이용하여 크루스칼알고리즘을 풀면 된다.

 

<전체코드>

import java.util.*;

class Solution {
    
    static class vertex implements Comparable<vertex>{
        
        int u;
        int v;
        int weight;
        
        vertex(int u, int v, int weight){
            this.u = u;
            this.v = v;
            this.weight = weight;
        }
        
        @Override
        public int compareTo(vertex v){
            return this.weight - v.weight;
        }
    }
    
    static int[] parent;
    public int solution(int n, int[][] costs) {
        int answer = 0;
        
        parent = new int[n];
        for(int i = 0 ; i < n ; i++){
            parent[i] = i;
        }
        
        PriorityQueue<vertex> pq = new PriorityQueue<vertex>();
        for(int i = 0 ; i < costs.length ; i++){
            pq.add(new vertex(costs[i][0], costs[i][1], costs[i][2]));
        }           
        
        while(!pq.isEmpty()){
            vertex top = pq.poll();
            
            int a = find(top.u);
            int b = find(top.v);
            
            if(a == b){
               continue;
            }
            
            union(a,b);
            answer += top.weight;            
        }
        
        return answer;
    }
    
    static int find(int a){
        if(parent[a] == a){
            return a;
        }
        
        return parent[a] = find(parent[a]);
    }
    
    static void union(int a, int b){
        int aRoot = find(a);
        int bRoot = find(b);
        
        if(aRoot != bRoot){
            parent[aRoot] = b;
        }
        
        return;
    }
}

'알고리즘 공부 > 탐욕알고리즘(Greedy)' 카테고리의 다른 글

[백준] 1461 도서관  (0) 2021.08.22
[프로그래머스] 단속카메라  (0) 2021.06.07
[프로그래머스] 조이스틱  (0) 2021.05.27
백준 1744 (수 묶기)  (0) 2021.01.22
백준 2873 (롤러코스터)  (0) 2021.01.21