문제풀이/백준

[백준]20010: 악덕 영주 혜유 - JAVA

빈둥벤둥 2021. 7. 7. 17:08

[백준]20010: 악덕 영주 혜유

 

20010번: 악덕 영주 혜유

FT온라인 게임에서 치열한 경쟁을 통해 영주가 된 혜유는 퀘스트를 받았다. 퀘스트의 내용은 자신이 관리하고 있는 마을 사이에 교역로를 건설하여 마을 간 교류를 활성화시키는 것이다. 이때,

www.acmicpc.net

풀이

🪑 MST를 구하는 활용문제이다.

 

문제의 조건들을 정리해보자.

  • 마을간 교역로는 양방향이다.
  • 모든 마을은 연결되어있다.
  • 구하는 값은 MST 비용과 MST 내에서 가장 먼 노드간의 거리이다.

 

🔧 이제 문제 풀이 과정을 생각해 보자.

  1. 마을 간 교역로 정보를 입력 받은 후 MST를 구한다. 
  2. MST를 저장해 둔 다음 MST를 내에서 DFS로 가장 먼 노드간의 거리를 구한다.
  3. 가장 먼 노드간의 거리를 구하기 위해선 먼저, 한 정점에서 가장 먼 노드를 구한 다음 그 정점에서 다시 가장 먼 노드를 구하면 된다. (백준 1167: 트리의 지름 참고)

 

🔹 MST를 구한다.

- MST알고리즘은 대표적으로 prim, kruskal이 있다. 나는 최소 간선 트리로 선택된 간선의 정보를 저장해 주기 위해 kruskal 알고리즘을 사용하였다. 

 

🔹 DFS로 가장 먼 노드간의 거리를 구한다.

- MST로 선택된 간선들의 정보를 가지고 DFS 탐색을 진행한다.

- 가장 먼 노드 사이의 거리를 구하는 방법은 먼저 한 정점에서 가장 먼 노드를 구한 다음, 그 정점에서 다시 가장 먼 노드까지의 거리를 구하면 된다. (백준 1167: 트리의 지름 참고)

- 해당 방법으로 가장 먼 노드간의 거리를 구해주면 된다.

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import java.util.*;
 
public class Main {
 
    static PriorityQueue<Node> q = new PriorityQueue<>();
    static ArrayList<Node>[] MST;
    static int[] parent;
    static int n, k;
    static boolean[] visited;
    static int max;
    static int startNode;
 
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        
        n = scan.nextInt();
        k = scan.nextInt();
 
        MST = new ArrayList[n]; //최소 간선 트리 정보를 저장하는 리스트
        for(int i = 0; i < n; i++) {
            MST[i] = new ArrayList<>();
        }
 
        for(int i = 0; i < k; i++) {
            int s = scan.nextInt();
            int e = scan.nextInt();
            int cost = scan.nextInt();
            q.offer(new Node(s, e, cost));
        }
        int min = kruskal(); //MST 비용을 구한다.
       
        max = Integer.MIN_VALUE;
        visited = new boolean[n];
        visited[0= true;
        dfs(00);
 
        max = Integer.MIN_VALUE;
        visited = new boolean[n];
        visited[startNode] = true;
        dfs(startNode, 0);
 
        System.out.println(min);
        System.out.println(max);
    }
 
    public static void dfs(int node, int total) {
        if(max < total) {
            max = total;
            startNode = node;
        }
 
        for(int i = 0; i < MST[node].size(); i++) {
            Node next = MST[node].get(i);
            if(!visited[next.e]) {
                visited[next.e] = true;
                dfs(next.e, total + next.cost);
            }
        }
    } 
 
    public static int kruskal() {
        parent = new int[n];
        for(int i = 0; i < n; i++) {
            parent[i] = i;
        }
 
        int min = 0;
        while(!q.isEmpty()) {
            Node current = q.poll();
 
            int p1 = find(current.s);
            int p2 = find(current.e);
 
            if(p1 != p2) {
                union(p1, p2);
                MST[current.s].add(new Node(current.e, current.cost));
                MST[current.e].add(new Node(current.s, current.cost));
                min += current.cost;
            }
        }
        return min;
    }
 
    public static int find(int a) {
        if(parent[a] == a) return a;
        else return parent[a] = find(parent[a]);
    }
 
    public static void union(int a, int b) {
        parent[a] = b;
    }
 
    public static class Node implements Comparable<Node> {
        int s;
        int e;
        int cost;
 
        public Node(int s, int e, int cost) {
            this.s = s;
            this.e = e;
            this.cost = cost;
        }
 
        public Node(int e, int cost) {
            this.e = e;
            this.cost = cost;
        }
 
        @Override
        public int compareTo(Node n) {
            return this.cost - n.cost;
        }
    }
}
cs