티스토리 뷰

Algorithm/Solution

[백준 6497] - 전력난

기내식은수박바 2020. 3. 16. 21:54
반응형

 

문제

  • 성진이는 한 도시의 시장인데 거지라서 전력난에 끙끙댄다.
    • 그래서 모든 길마다 원래 켜져 있던 가로등 중 일부를 소등하기로 하였다.
    • 길의 가로등을 켜 두면 하루에 길의 미터 수만큼 돈이 들어가는데, 일부를 소등하여 그만큼의 돈을 절약할 수 있다.
  • 그러나 만약 어떤 두 집을 왕래할 때, 불이 켜져 있지 않은 길을 반드시 지나야 한다면 위험하다.
    • 그래서 도시에 있는 모든 두 집 쌍에 대해, 불이 켜진 길만으로 서로를 왕래할 수 있어야 한다.
  • 위 조건을 지키면서 절약할 수 있는 최대 액수를 구하시오.

 

입력

  • 입력은 여러 개의 테스트 케이스로 구분되어 있다.
  • 각 테스트 케이스의 첫째 줄에는 집의 수 m과 길의 수 n이 주어진다. (1 ≤ m ≤ 200000, m-1 ≤ n ≤ 200000)
  • 이어서 n개의 줄에 각 길에 대한 정보 x, y, z가 주어지는데, 이는 x번 집과 y번 집 사이에 양방향 도로가 있으며 그 거리가 z미터라는 뜻이다. (0 ≤ x, y < m, x ≠ y)
  • 도시는 항상 연결 그래프의 형태이고(즉, 어떤 두 집을 골라도 서로 왕래할 수 있는 경로가 있다), 도시상의 모든 길의 거리 합은 231미터보다 작다.
  • 입력의 끝에서는 첫 줄에 0이 2개 주어진다.

 

출력

  • 각 테스트 케이스마다 한 줄에 걸쳐 절약할 수 있는 최대 비용을 출력한다.

 

 

솔루션

  • 최소 스패닝 트리를 사용하는 간단한 문제이다.
  • 문제를 풀면서 한 가지 유의해야 할 점은 스패닝 트리를 이루는 간선의 총 비용을 구하는 것이 아니라 전체 간선의 총 비용에서 스패닝 트리를 이루는 간선의 비용을 빼서 나온 값을 구해야 한다.

 

Code

각 노드의 루트 노드를 본인으로 초기화하는 함수

1
2
3
4
public static void Initialize(int m) {
    for (int i = 0; i < m; i++)
        parent[i] = i;
}
cs

 

노드가 속한 집합의 루트 노드를 찾는 함수

1
2
3
4
5
6
public static int Find(int u) {
    if (parent[u] == u)
        return u;
 
    return parent[u] = Find(parent[u]);
}
cs

 

각 노드가 속한 집합을 합치는 합집합 연산 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void Union(int u, int v) {
    int uR = Find(u);
    int vR = Find(v);
 
    if (uR == vR)
        return;
 
    if (rank[uR] > rank[vR])
        Swap(uR, vR);
 
    parent[uR] = vR;
 
    if (rank[uR] == rank[vR])
        rank[uR]++;
}
cs

 

간선 객체를 생성하는 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
public 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;
    }
 
    public int compareTo(Edge e) {
        return this.cost - e.cost;
    }
}
cs

 

크루스칼 알고리즘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static int Kruskal(int n, int total) {
    int cost = 0, count = 0;
 
    while (!edgelist.isEmpty()) {
        Edge edge = edgelist.poll();
        
        if(count == n - 1)
            break;
 
        if (Find(edge.from) != Find(edge.to)) {
            Union(edge.from, edge.to);
            cost += edge.cost;
            count++;
        }
    }
 
    return total - cost;
}
cs

 

메인 함수

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
public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
 
    while (true) {
        StringTokenizer st = new StringTokenizer(br.readLine());
        int m = Integer.parseInt(st.nextToken());
        int n = Integer.parseInt(st.nextToken());
        
        if(m == 0 && n == 0)
            break;
 
        parent = new int[m];
        rank = new int[m];
        edgelist = new PriorityQueue<>();
 
        Initialize(m);
        
        int total = 0;
 
        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
 
            int from = Integer.parseInt(st.nextToken());
            int to = Integer.parseInt(st.nextToken());
            int cost = Integer.parseInt(st.nextToken());
 
            edgelist.offer(new Edge(from, to, cost));
            total += cost;
        }
 
        bw.write(Kruskal(n, total) + "\n");
    }
 
    bw.flush();
    bw.close();
    br.close();
}
cs

 

결과

반응형

'Algorithm > Solution' 카테고리의 다른 글

[백준 1003] - 피보나치 함수  (0) 2020.03.17
[프로그래머스] - 정수 삼각형  (0) 2020.03.16
[백준 1647] - 도시 분할 계획  (0) 2020.03.13
[백준 10774] - 저지  (0) 2020.03.12
[백준 10775] - 공항  (0) 2020.03.12
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
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
글 보관함