1. 문제 - 백준 16562 친구비
https://www.acmicpc.net/problem/16562
💡알고리즘 - DFS or 유니온파인드
- "친구의 친구는 친구다" 즉, 친구 무리를 짓는다는 점에서 DFS 혹은 유니온파인드를 이용할 수 있다.
- 각 친구 무리 별로 친구비가 가장 적은 친구비를 합쳐 준석이가 가진 비용과 비교한다.
✅ DFS 풀이
import sys
sys.setrecursionlimit(10**8)
n, m, k = map(int, input().split())
money = [0] + list(map(int, input().split()))
graph = [[] for _ in range(n+1)]
for _ in range(m):
v, w = map(int, input().split())
graph[v].append(w)
graph[w].append(v)
def dfs(node):
global temp
visited[node] = True
temp = min(temp, money[node])
for i in graph[node]:
if not visited[i]:
dfs(i)
answer = 0
visited = [False] * (n+1)
for i in range(1, n+1):
if not visited[i]:
temp = 1e9
dfs(i)
answer += temp
if answer <= k:
print(answer)
else:
print("Oh no")
- 친구의 친구는 친구다 --> 같은 친구 그룹을 형성하는 친구 중에 최소 비용을 가진 친구에게 친구비를 주면 된다.
- dfs로 같은 친구 무리들끼리 방문처리하며 무리 내부에서의 temp 라는 친구비 최소값을 갱신하고, answer에 더해나간다.
✅ 유니온파인드 풀이
n, m, k = map(int, input().split())
money = [0] + list(map(int, input().split()))
answer = 0
parent = [i for i in range(n+1)]
def find(x):
if parent[x] == x:
return x
parent[x] = find(parent[x])
return parent[x]
def union(x, y):
root_x = find(x)
root_y = find(y)
if money[root_x] > money[root_y]:
parent[root_x] = root_y
else:
parent[root_y] = root_x
for _ in range(m):
v, w = map(int, input().split())
union(v, w)
for i in range(1, n+1):
if i == parent[i]:
answer += money[i]
if answer <= k:
print(answer)
else:
print("Oh no")
- union 함수: 친구와 친구끼리 무리를 만드는 (부모 노드를 같게 하는) 함수인데, 친구 비용이 제일 작은 친구를 부모 노드로 만들어야하므로 친구 비용이 큰 친구의 부모 노드를 친구 비용이 작은 친구의 부모 노드를 만드는 방식으로 union을 실행한다.
2. 문제 - 백준 1976 여행 가자
https://www.acmicpc.net/problem/1976
💡알고리즘 - 유니온파인드
- 도시들간의 연결 여부가 주어지고, 여행 계획에 속한 도시들을 차례대로 방문할 수 있는지 확인 -> 같은 그룹인지 확인
- 같은 그룹인지 확인하려면? find를 통해 부모 노드를 찾아 union을 통해 같은 집합으로 묶어준다.
✅ 풀이
n = int(input())
m = int(input())
graph = [[]]
for _ in range(n):
graph.append([0] + list(map(int, input().split())))
cities = list(map(int, input().split()))
parent = [i for i in range(n+1)]
def find(x):
if parent[x] == x:
return x
parent[x] = find(parent[x])
return parent[x]
def union(x, y):
root_x = find(x)
root_y = find(y)
if root_x > root_y:
parent[root_x] = root_y
else: # 반대 케이스
parent[root_y] = root_x
for i in range(1, n+1):
for j in range(1, n+1):
if graph[i][j]:
union(i, j)
x = find(cities[0])
answer = "YES"
for city in cities[1:]:
if parent[city] != x: # 위에서 union을 통해 집합을 합쳤을 때, 루트노드가 다르다면 해당 경로대로 방문할 수 없다는 의미임
answer = "NO"
break
print(answer)
- 도시의 번호가 1부터 N까지 차례대로 주어지므로, union시 연결관계가 있는 노드끼리 부모노드가 더 작은 그룹끼리 합쳐준다.
- 그리고 첫번째 도시의 부모노드 x와 다른 도시들의 부모 노드가 다르다는 것은, 같은 그룹에 있는 경로가 아니므로 방문할 수 없다. 따라서 이때 NO를 출력한다.
'⚙️ 알고리즘 > 문제풀이' 카테고리의 다른 글
[Python] 백준 19238 스타트 택시 (0) | 2025.08.04 |
---|---|
[Python] 백준 2504 괄호의 값 (0) | 2025.08.04 |
[Python] 프로그래머스 퍼즐 게임 챌린지 (0) | 2025.07.30 |
[Python] 백준 17142 연구소3 (0) | 2025.07.29 |
[Python] 프로그래머스 스티커 모으기(2), 백준 21610 마법사 상어와 비바라기, 프로그래머스 표 병합 (0) | 2025.07.28 |