새소식

반응형
Algotithms

[백준] 16562 친구비

  • -
728x90
반응형

문제

  • 학생이 N명인 학교에서 K원을 가진 준석이가 가장 적은 비용으로 모두와 친구가 되는 방법은?
    • 1 <= N <= 10,000
    • 1 <= K <= 10,000,000
  • 학생 i 에게 $A_i$ 만큼의 돈을 주면 그 학생과 1달간 친구가 된다.
    • 1 <=  $A_i$ <= 10,000
  • 친구의 친구도 친구다. (친구 관계 수는 M개 있다)
    • 0 <= M <= 10,000
  • 준석이가 친구를 다 사귈 수 없다면 "Oh no" 출력한다.

 

풀이 1

  • 비용이 적은 학생부터 시작 + 그래프 탐색으로 경우의 수 줄이기
    • => 연결된 친구 관계에서 가장 비용이 적은 친구에게만 돈을 주면 된다.
  • 시간 복잡도 : O(N * (N+E)) $\simeq$ O($N^2$)  => 가능하다! 

 

import heapq
import sys
sys.setrecursionlimit(10**9)    # 재귀 제한

# 친구 관계 확인하기
def check(graph, x, visited):
    for i in graph[x]:
        if not visited[i] :
            visited[i] = True
            check(graph, i, visited)

N, M, K = map(int, input().split())     # 학생 수, 친구 관계 수, 돈
price = list(map(int, input().split())) # 친구비

# 친구 관계 그래프 - 중복 제거를 위해 set으로 
graph = [ set() for _ in range(N+1) ]   
for _ in range(M):
    a, b = map(int, input().split())
    graph[a].add(b)
    graph[b].add(a)

# 친구비가 적은 학생 순으로 정렬하기
price_sort = []
for i in range(N):
    heapq.heappush(price_sort, (price[i], i+1))

# 한 명씩 친구 사귀기
money = 0
visited = [False] * (N+1)
while price_sort:
    cost, now = heapq.heappop(price_sort)

    if not visited[now]:    # 아직 친구가 아니라면
        money += cost           # 비용 지불
        visited[now] = True     # 방문 표시
        check(graph, now, visited)  # 친구의 친구는 내 친구~
    

print(money) if money <= K else print("Oh no")

 

풀이 2

  • 각 친구 관계에 대한 그래프를 만든다는 점에서 유니온 파인드로 해결할 수 있다.
  • 친구의 친구 관계로 서로 연결된 그래프를 만들고 그 중 가장 최소 비용을 가진 친구를 대장(부모)으로 둔다.

 

# 친구 대장 찾기
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, price):
    a = find_parent(parent, a)
    b = find_parent(parent, b)
    
    if price[a] < price[b] :
        parent[b] = a
    else:
        parent[a] = b
	
# 입력 받기
N, M, K = map(int, input().split())     # 학생 수, 친구 관계 수, 돈
price = [0] + list(map(int, input().split()))   # 친구비

parent = [i for i in range(N+1)]        # 각 친구 그룹의 대장

# 친구 그룹 별로 묶기
for _ in range(M):
    a, b = map(int, input().split())
    union_parent(parent, a, b, price)

money = 0
friend = set()
for i in range(1, N+1):
    x = find_parent(parent, i)      # 속한 친구 그룹의 대장찾기
    if x not in friend :   # 아직 친구가 아니면
        money += price[x]
        friend.add(x)

print(money) if money <= K else print("Oh no")

 

 

 

References

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.