알고리즘 풀이/백준

[백준 6497] 전력난

mhko411 2021. 4. 23. 13:53
728x90

문제

모든 길에 가로등이 켜져있는데 어떠한 가로등을 소등하면 하루에 길의 미터 수만큼 절약할 수 있다. 하지만 어떤 두 집을 왕래할 때 불이 켜져있지 않다면 위험하다. 따라서 도시에 있는 모든 두 집 쌍에 대해 불이 켜진 길만으로 서로를 왕래할 수 있어야한다. 이 조건을 지키면서 절약할 수 있는 최대 액수를 구하시오.

 

입력

여러 개의 테스트 케이스가 주어진다.

첫째 줄에는 집의 개수 M과 길의 수 N이 주어진다. 만약 M과 N이 0이라면 더 이상의 테스트 케이스는 없다.

이어서 N개의 줄에 길에 대한 정보가 입력되고 x, y, z로 이루어진다.

x번과 y번 집 사이에 양방향 도로가 있으며 z미터라는 의미이다.

 

출력

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


접근

모든 두 집 쌍에 대해 불이 켜진 길만으로 왕래를 해야한다는 조건은 M개의 집이 있을 때 M-1개의 간선에 가로등을 하나씩 켜고 이 비용을 최소로 해야한다는 것이다. 따라서 연결정보가 주어졌을 때 그래프 내에서 최소 신장 트리를 구해야한다. 그리고 총 비용에서 빼주면 해를 구할 수 있다.

 

구현

- 크루스칼 알고리즘을 적용시켰다.

- 먼저 연결정보를 입력받으면서 총 비용을 total에 저장한다.

    graph = []
    home_list = [m for m in range(M)]

    total = 0
    for _ in range(N):
        x, y, z = map(int, input().split())
        total += z
        graph.append((x, y, z))

 

- 이제 비용을 기준으로 오름차순 정렬을 하고

- edge_count가 M-1개가 될 때까지 연결해야하는 간선을 찾는다.

- 간선을 찾을 때는 연결된 두 개의 집이 같은 집합에 속해있지 않을 때이며 

- 같은 집합에 속해있지 않을 때 edge_count를 1증가시키고 x와 y를 union해준다. 

- 또한 answer를 z만큼 증가시킨다.

- 최종적으로 total과 answer를 뺀 값이 해가 될 것이다.

    graph = sorted(graph, key=lambda x: x[2])

    edge_count = 0
    answer = 0
    for x, y, z in graph:
        if find_set(x) != find_set(y):
            union(x, y)
            edge_count += 1
            answer += z
        if edge_count == M-1:
            break

전체 코드

import sys
input = sys.stdin.readline

def find_set(a):
    if home_list[a] == a:
        return a
    else:
        b = find_set(home_list[a])
        home_list[a] = b
        return b

def union(a, b):
    a = find_set(a)
    b = find_set(b)
    if a != b:
        home_list[b] = a

while True:
    M, N = map(int, input().split())
    if M == 0 and N == 0:
        break

    graph = []
    home_list = [m for m in range(M)]

    total = 0
    for _ in range(N):
        x, y, z = map(int, input().split())
        total += z
        graph.append((x, y, z))

    graph = sorted(graph, key=lambda x: x[2])

    edge_count = 0
    answer = 0
    for x, y, z in graph:
        if find_set(x) != find_set(y):
            union(x, y)
            edge_count += 1
            answer += z
        if edge_count == M-1:
            break

    print(total - answer)

'알고리즘 풀이 > 백준' 카테고리의 다른 글

[백준 1647] 도시 분할 계획  (0) 2021.04.24
[백준 1504] 특정한 최단 경로  (0) 2021.04.23
[백준 1976] 여행가자  (0) 2021.04.23
[백준 1922] 네트워크 연결  (0) 2021.04.22
[백준 1717] 집합의 표현  (0) 2021.04.22