코테에 유니온파인드가 나오나...?라는 의구심을 품고 푼 문제
유니온 파인드 문제를 처음 풀어봐서 주석을 많이 달아놨다.
이 문제를 푸는 방법은
끊을 간선을 제외한 모든 간선을 먼저 연결하고 끊을 간선들을 역순으로 하나씩 연결한다.
배열의 부모노드의 값은 음수로 집합의 개수가 저장되어있다는 것이 중요하다.
<Main>
처음 배열은 -1로 초기화한다.
edges,div로 연결할 리스트와 제거할 리스트를 입력받는다.
연결할 리스트의 개수만큼을 돌면서 제거될 연결이 아니라면 연결해준다.(union)
answer 변수를 0으로 초기화한다.
제거할 연결을 역순으로 union한다. union은 각 집합의 개수의 곱을 반환하므로 반환값을 answer에 더한다.
answer을 출력한다.
<union>
; 각 원소를 연결해주고 두 그룹의 크기의 곱을 반환해주는 함수
find를 통해서 부모노드의 번호를 구한다.
부모노드의 값은 음수로 집합의 개수를 갖고있으므로 두개의 값을 곱하고 res로 저장해둔다.
(둘다 음수이므로 곱하면 양수가 되어서 우리가 원하는 값이 잘 나온다.)
만약 부모노드가 동일하다면 두 원소는 같은 집합의 원소이므로 return 0을 한다.
만약 부모노드가 동일하지 않다면 한 부모노드의 값을 다른 부모 노도의 값에 더하여 저장한다.
각 집합의 원소의 개수를 저장하고 있기에 더하는 것이다. 이제 두 집합은 하나의 집합이다.
그리고 더함을 받지않은 부모노드는 이제 더함을 받은 부모노드의 번호를 값으로 갖고있다.
<find>
; 부모 노드의 번호를 반환하는 함수
부모노드라면 집합의 개수가 음수로 저장되어있다는 것을 생각하자.
만약 값이 음수라면 부모노드라는 뜻이므로 번호를 반환한다.
만약 값이 음수가 아니라면 부모노드가 아닌 노드라는 의미이므로
재귀를 통해서 부모노드를 찾고 그 과정에서 부모노드의 값으로 배열의 값이 변경된다.
1번은 -4로 4개의 원소를 가진 집합의 부모노드라는 것을 알 수 있다.
2,3,4번은 1번이 부모노드인 집합의 구성원임을 알 수 있다.
코드 :
# u배열, a와 b를 union
def union(u, a, b):
# 각각의 부모를 구함
a = find(u, a)
b = find(u, b)
# union할 두 그룹의 크기의 곱
res = u[a] * u[b]
# 같은 집합이라면
if a == b :
return 0
# 같은 집합이 아니라면
else :
u[a]+=u[b]
u[b] = a
return res
# 부모 노드를 찾는 함수
def find(u, x):
# 부모노드라면
if u[x] < 0:
return x
# 부모노드가 아니라면
# 재귀를 이용해서 부모노드를 찾음
u[x] = find(u, u[x])
return u[x]
if __name__=="__main__" :
n, m, q = map(int, input().split())
u = [-1] * (n + 1)
# 끊을 간선을 제외한 모든 간선을 먼저 연걸해주고 끊을 간선들을
# 역순으로 하나씩 연결
# 부모노드에 음수로 갯수를 저장한다.
# 연결할 리스트
edges = [list(map(int, input().split())) for _ in range(m)]
# 제거할 리스트
div = [int(input()) for _ in range(q)]
div_set = set(div)
# 제거되지 않는 연결들에 대해 union 처리
for i in range(m):
# 제거할 간선이라면 pass
if (i+1) in div_set:
continue
# 제거할 간선이 아니라면 연결
union(u, edges[i][0], edges[i][1])
# 연결을 끊는데 들어가는 비용
answer = 0
# 제거할 연결을 역순으로 union
for i in range(q-1, -1, -1):
answer += union(u, edges[div[i]-1][0], edges[div[i]-1][1])
print(answer)
참고 영상 :
https://www.youtube.com/watch?v=AMByrd53PHM&t=107s
'알고리즘 > 백준 문제풀이' 카테고리의 다른 글
[Python/BOJ] 백준 1039 교환_(신박한)BFS (0) | 2022.08.11 |
---|---|
[Python/BOJ] 백준 14391 종이조각 _비트마스킹 (0) | 2022.08.11 |
[Python/BOJ] 백준 15927 회문은 회문이 아니야!!_문자열 (0) | 2022.08.10 |
[삼성SW역량][Python/BOJ] 백준 17143 낚시왕_구현 (0) | 2022.08.10 |
[Python/백준]12865번_평범한 배낭(DP, 냅색) (0) | 2022.08.06 |