BOJ 1043 거짓말

첫 접근 방법
처음 생각한 알고리즘은 너무 복잡했다.
- 파티에 참여한 사람들로 그래프를 구성한 뒤에 진실을 아는 사람들을 시작점으로 하여 bfs를 진행
- 연결되어 있다면 연결된 사람들도 진실을 아는 사람이므로 진실을 아는 사람들 list에 추가
- 다시 파티에 참여한 사람들 정보로 한명이라도 진실을 아는 사람들 list에 존재한다면 그 party는 count x
–> 한 파티에 참여하는 사람들이 많을 때 graph에 관계를 저장하는게 복잡함
검색하여 구한 방법 1
bfs를 진행하지 않고도 구할 방법을 찾았다. bfs를 굳이 하지 않고
- 파티에 참여한 사람들 중에 진실을 아는 사람 (know)집합에 포함되는 사람들이 있다면 나머지 파티원들을 know에 추가 -> 이렇게 party 수만큼 반복하면 서로 관계를 다 집합에 넣을 수 있음
- 다시 파티에 참여한 사람들 정보로 한명이라도 진실을 아는 사람들 list에 존재한다면 그 party는 count x
정답 코드 1
import sys
input = sys.stdin.readline
"""
party에서 진실을 아는 사람이 party에 존재한다면 나머지 사람들도 진실을 안다고 볼 수 있으므로
party를 아는 사람 집합에 나머지들도 추가함
"""
n,m = map(int, input().split())
temp = list(map(int, input().split()))
if temp[0]==0:
print(m)
else:
know = set()
for t in temp[1:]:
know.add(t)
parties = []
for _ in range(m):
party = set(list(map(int, input().split()))[1:])
parties.append(party)
#순서에 영향받지 않도록 m번 반복
for _ in range(2):
for party in parties:
if party & know:
know = know.union(party)
ans = 0
for party in parties:
if not (party & know):
ans+=1
print(ans)
검색하여 구한 방법 2
- union find 알고리즘을 통해 party에서 진실을 아는 사람이 존재한다면 나머지 사람들의 부모를 진실을 아는 사람으로 설정
- 다시 party 안의 각 사람들에 대해 순회를 돌면서 부모가 진실을 아는 사람 집합 안에 존재한다면 이 party에는 거짓말을 하지 못한다.
정답 코드 2 (분리집합)
import sys
input = sys.stdin.readline
n,m = map(int, input().split())
temp = list(map(int, input().split()))
if temp[0]==0:
print(m)
else:
know = set()
for t in temp[1:]:
know.add(t)
parents = [i for i in range(n+1)]
def find(parents, c):
if parents[c] != c:
parents[c] = find(parents, parents[c])
return parents[c]
def union(parents, a, b, know):
a = find(parents, a)
b = find(parents, b)
if a in know and b in know:
return
elif a in know:
parents[b] = a
elif b in know:
parents[a] = b
else:
if b > a:
parents[a] = b
else:
parents[b] = a
parties = []
for _ in range(m):
party = list(map(int, input().split()))
party_len = party[0]
party = party[1:]
parties.append(party)
for i in range(party_len-1):
union(parents, party[i], party[i+1], know)
ans = 0
for party in parties:
in_party = False
for i in range(len(party)):
if find(parents, party[i]) in know:
in_party = True
if not in_party:
ans+=1
print(ans)
느낀 점
union-find 알고리즘을 이론으로만 알고 있었는데 문제에 실제로 적용하는 것은 처음이라 풀이를 떠올리지 못한 것 같다.