Home 어두운 길 University of Ulm Local Contest 그래프
Post
Cancel

어두운 길 University of Ulm Local Contest 그래프

한 마을은 N개의 집과 M개의 도로로 구성되어 있습니다. 각 집은 0번부터 N-1번까지의 번호로 구분됩니다. 모든 도로에는 가로등이 구비되어 있는데 특정한 도로의 가로등을 하루 동안 켜기 위한 비용은 해당 도로의 길이와 동일합니다. 예를 들어 2번 집과 3번 집 사이를 연결하는 길이가 7인 도로가 있다고 해봅시다. 하루 동안 이 가로등을 켜기 위한 비용은 7이 됩니다.

정부는 일부 가로등을 비활성화하되, 마을에 있는 임의의 두 집에 대하여 가로등이 켜진 도로만으로도 오갈 수 있도록 만들고자 합니다. 결과적으로 일부 가로등을 비활성화하여 최대한 많은 금액을 절약하고자 합니다. 마을의 집과 도로 정보가 주어졌을 때 일부 가로등을 비활성화하여 절약할 수 있는 최대 금액을 출력하는 프로그램을 작성하세요

입력 예시 N M (집의수 N, 도로의수 M) X Y Z (X번집과 Y번집 사이의 도로(비용) Z 일부 가로등을 비활성화하여 절약할 수 있는 최대 금액을 구하는데

제 생각에는 보자마자 신장트리 문제 같았습니다. 임의의 두 집에 대하여 가로등이 켜진 도로만으로 오갈 수 있으니 이제 크루스칼 알고리즘을 사용하면 됩니다. 하지만 도로의 전체 비용을 구하는 것이 아닌 절약하는 비용입니다.

그러니 전체 가로등을 켜는 비용에 최소 비용을 빼면 되겠네요

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
#특정 원소가 속한 집합을 찾기
def find_parent(parent, x):
    #로트 노드가 아니라면, 로트 노드를 찾을 때까지 재귀적으로 호출
    if parent[x] != x:
        parent[x] = find_parent(parent, parent[x])
    return parent[x]

#두 원소가 속한 집합을 찾기
def union_parent(parent,a,b):
    a = find_parent(parent,a)
    b = find_parent(parent,b)
    if a < b:
        parent[b] = a
    else:
        parent[a] = b

#노드의 개수와 간선의 개수 입력받기
n,m = map(int,input().split())
parent = [0]*(n+1) #부모 테이블 초기화

#모든 간선을 담을 리스트와 최종 비용을 담을 변수
edges = []
result = 0

#부모 테이블상에서, 부모를 자기 자신으로 초기화
for i in range(1,n+1):
    parent[i] = i
    
#모든 간선에 대해서 정보를 입력받기
for _ in range(m):
    x, y, z = map(int,input().split())
    #비용순으로 정렬하기 위해서 튜플의 첫 번째 원소를 비용으로 설정
    edges.append((z,x,y))

시작은 전과 비슷합니다. 일단 원소가 속한 집합(루트노드)를 찾고, 두 원소가 속한 집합을 합치는 함수를 만들고

값을 입력받고 부모 노드를 자기 자신으로 초기화를 합니다.

이때 간선을 입력받을때 비용을 기준으로 하기 위해서 z를 먼저 받습니다.

1
2
3
#간선을 비용순으로 정렬
edges.sort()
total = 0 #전체 가로등 비용

그러면 간선은 z를 기준으로 먼저 정렬이 이루어지고 전체 입력받을 가로등 비용은 0으로 초기화를 합시다.

그 다음 최소비용으로 이루어지는 값 result는 위에서 초기화를 합니다.

1
2
3
4
5
6
7
8
9
10
#간선을 하나씩 확인하며
for edge in edges:
    cost, a, b = edge
    total += cost
    #사이클이 발생하지 않는 경우에만 집합에 포함
    if find_parent(parent, a) != find_parent(parent, b):
        union_parent(parent, a, b)
        result += cost
        
print(total - result)

그리고 간선을 하나씩 확인하면서 사이클이 발생하지 않는 경우에만(두 집합의 부모가 같지 않을 경우)에만 합치고 비용을 계산하여 result를 갱신을 하고

최종적으로 전체 비용에서 result를 빼는 것으로 출력을 합니다.

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.

탑승구 그래프

행성터널 백준 2887번 그래프