문제 접근 및 공부 내용, 풀이는 모두 하단 코드에 "주석"으로 포함되어 있으니 참고해주세요.
문제 유형 보기
https://www.acmicpc.net/problem/1976
풀이
성공, 주석 제거 버전
import sys
input = sys.stdin.readline
def find(x):
if parent[x] != x:
parent[x] = find(parent[x])
return parent[x]
def union(x, y):
x_root = find(x)
y_root = find(y)
if x_root == y_root:
return
if rank[x_root] > rank[y_root]:
parent[y_root] = x_root
elif rank[x_root] < rank[y_root]:
parent[x_root] = y_root
else:
parent[y_root] = x_root
rank[x_root] += 1
n = int(input())
m = int(input())
graph = [list(map(int, input().split())) for _ in range(n)]
travels = list(map(int, input().split()))
parent = list(range(n+1))
rank = [0] * (n+1)
for i in range(n):
for j in range(i):
if graph[i][j] == 1:
union(i + 1, j + 1)
travel_set = {find(x) for x in travels}
print("YES" if len(travel_set) == 1 else "NO")
성공, 주석 포함 버전
import sys
input = sys.stdin.readline
def find(x):
if parent[x] != x:
# 트리 구조 변경하면서 root를 찾아옴
parent[x] = find(parent[x])
return parent[x]
def union(x, y):
x_root = find(x)
y_root = find(y)
if x_root == y_root:
return
if rank[x_root] > rank[y_root]:
parent[y_root] = x_root
elif rank[x_root] < rank[y_root]:
parent[x_root] = y_root
else:
parent[y_root] = x_root
rank[x_root] += 1
# 여기까지는 정말 기본적인 유니온 파인드 ADT 구현
# 여행을 가는 데,
# 입력 :
# 첫 줄 : 도시 수 N
# 둘째 줄 : 여행 계획에 속한 도시들 수 M
# 그 담부터 : 인접 행렬 N x N
# 마지막 : 여행 계획(방문할 도시들)
# 도시 번호는 1, 2, ..., n임
n = int(input())
m = int(input())
graph = [list(map(int, input().split())) for _ in range(n)]
travels = list(map(int, input().split()))
# 아, 이거 travels에 속한 애들이, 지금은 서로소 집합인데,
# 얘네들이 결국 하나의 집합을 이루면 YES 못하면 NO 출력(삼항)
# 그러면, parents 놓고, 거기에 모든 노드들 넣고, 연결시킨다음에,
# 마지막에 최종 parents 보고서 거기 중에 travels에 속한 놈들의 find(travel)이
# 모두 같은 지 비교하면 됨.
# 모두 같은 지 비교하는 법은 여러 개 있을듯?
# 그냥 하나씩 find 해서 그 결과 반복문으로 비교해, 이전과 다르면 NO 출력
# 다른 거 없이 반복문 다 헤쳐나갔으면 YES 출력 이렇게 할 수도 있을거고
# 아님 set() 한 다음에 길이 재서 1이냐 아니냐 할 수도 있을듯.
parent = list(range(n+1))
rank = [0] * (n+1)
# 반복문 돌면서 union 호출하면 될듯.
for i in range(n):
for j in range(i):
if graph[i][j] == 1:
union(i + 1, j + 1)
travel_set = {find(x) for x in travels}
print("YES" if len(travel_set) == 1 else "NO")
강사님 정답 풀이 확인
group = find(plans[0]) # 출발 도시의 집합이 기준이 됨
result = "YES"
for plan in plans[1:]:
if group != find(plan):
result = "NO" # 하나의 도시라도 다른 집합에 속하면 여행할 수 없음
break
print(result)
# 이렇게 비교할 수도 있다.
# 사실, 엄밀히 따지면 내 풀이보다 이렇게 푸는 게 더 실행 시간 상에서 이득임.
# 왜냐하면, 얘는 마치 함수의 early return처럼, 여행이 불가능하면 바로 break 해버리기에,
# len(travels)만큼 모두 살피지 않아도 될 수 있으니 더 효율적임.
# 그러나, 내 코드는 set()을 쓰니 len(travels) 만큼을 다 뒤져봐야함.
# 어쨌든간에, 결국 웬만해서는 저 메인 이중 루프가 대충 (N^2)/2 정도 소요될 텐데,
# M은 1000 이하니 M만큼 더 걸려봤자 그다지 크지도 않고 (N^2)/2의 최악의 경우보다도 작음.
# 근데 굳이 set을 쓸 이유도 없고,
# 나중이 어렇게 끝처리 해야하는 문제 또 만나면 그냥 위처럼 할듯?
# 모두 값이 같은지 체크는 set()을 사용하면 O(n)으로 검사가 가능하다는 것만 알고 가자.
250228 재풀이
그냥 백준 스타일대로 바로 입력받았음
import sys
input = sys.stdin.readline
# 임의의 두 도시 사이에 길이 있을 수도 없을 수도 있음.
# 즉, 여행 계획이 불가능한 계획일 수도 있음.
# 여행 가능한지 불가능한지 출력
# 도시 수 n, 여행 계획 속한 도시 수 m,
# 인접 행렬로 연결 정보 나오고,
# 마지막으로 여행 계획 주어짐.
# 간선 정보는 있는데, 무방향이고, 가중치 없음.
# 여행 가능하단 건, E C B C D 얘네가 모두 하나의 집합에 속해 있으면 되는 거임.
# 즉, 간선 정보를 가지고 union을 다 한 다음에, 쟤네들 find 다 때려서
# 모두 같으면 YES, 하나라도 다르면 NO 출력하면 됨.
# 근데 여행 일정은 순서대로 가야 하는데, 갔던 길 다시 갈 수도 있고,
# 뭐 결국 같은 집합이기만 하면, 여러 번 방문 가능하니까 노상관 같은데?
def find(x):
if parent[x] != x:
parent[x] = find(parent[x])
return parent[x]
def union(x, y):
x_root = find(x)
y_root = find(y)
if x_root == y_root:
return
if rank[x_root] > rank[y_root]:
parent[y_root] = x_root
elif rank[y_root] > rank[x_root]:
parent[x_root] = y_root
else:
parent[y_root] = x_root
rank[x_root] += 1
n = int(input())
m = int(input())
parent = list(range(n + 1))
rank = [0] * (n + 1)
for i in range(n):
line = list(map(int, input().split()))
for j in range(n):
if line[j] == 1:
union(i + 1, j + 1)
plans = list(map(int, input().split()))
group = find(plans[0])
for plan in plans[1:]:
if find(plan) != group:
print('NO')
break
else:
print('YES')
'Algorithms and Languages > 파이썬 알고리즘 문제풀이' 카테고리의 다른 글
[Python/백준] 2628. 종이자르기 (0) | 2025.02.28 |
---|---|
[Python/백준] 1753. 최단거리 (0) | 2025.02.28 |
[Python/백준] 1647. 도시 분할 계획 (0) | 2025.02.28 |
[Python/DailyAlgo, 백준] 86. 최소 신장 트리, 1197. 최소 스패닝 트리, 89. 동기화 서버 구축 (0) | 2025.02.27 |
[Python/백준] 20040. 사이클 게임 (0) | 2025.02.27 |