728x90
이분 매칭
- A 집단이 B 집단을 선탁하는 방법에 대한 알고리즘
- 즉, 2개의 정점 그룹이 있을 때, 그룹에서 그룹으로 정점의 최대 매칭을 찾는 알고리즘이다.
위와 같은 두 그룹의 정점이 있을 때 각 그룹을 연결할 수 있는 간선의 정보는 아래와 같다.
A : 2, 5
B : 2, 3, 4
C : 1, 5
D: 1, 2, 5
E : 2
- 이 정보를 가지고 정점을 한 번만 사용해서 최대한 많은 정점이 매칭되게 해보자.
- DFS와 visted 배열을 활용하여 구해준다.
우선 A가 매칭가능한 번호 중 빠른 번호인 2를 매칭 시켜준다.
- 이후 B를 매칭 시켜주는데 B가 연결할 수 있는 가장 빠른 번호도 2이므로
- A로 돌아가 매칭 시킬 수 있는 다른 정점이 있는지 살펴본 후 존재한다면 A가 양보해준다.
- 따라서, A - 5, B - 2와 매칭이 된다.
- 다음 C를 매칭 시켜주는데 바로 1과 매칭 시켜줄 수 있다.
- D를 매칭시키기 위하여 보니까 1과 매칭을 시켜주려니 이미 C가 1과 짝이기 때문에
- B의 케이스와 마찬가지로 C로 돌아가서 새로 매칭을 시켜주려고 한다.
- 근데 이 때, C가 매칭할 수 있는 다른 정점은 5번인데, 5번은 이미 A와 매칭이 되어있고
- A의 경우, 2번으로 돌아가려니 B가 매칭이 되어있다.
- 다시 B로 돌아가 B를 3번으로 매칭하니 아래와 같이
- A - 2, B - 3, C - 5, D - 1로 매칭이 가능해졌다.
- 남은 정점은 E번이므로 매칭을 해보려하지만 2번은 이미 A가 연결되어있고, A가 양보할 수 있는 정점이 없다.
- 따라서, 최대 매칭 수는 4가 된다.
- 아래는 DFS와 VISITED를 활용한 이분 매칭 알고리즘의 예시이다!
- 시간 복잡도는 O(V*E)이 된다.
- 양 쪽 정점의 개수를 서로 곱한 값
- 네트워크 플로우 -> 에드몬드 카프 알고리즘보다 월등히 빠르게 사용 가능하다.
# 현재 매칭을 시작할 번호를 인자로 받는다
def bipartite_matching(num):
# 매칭이 가능한 번호를 순회
for idx in alpha[num]:
# 만약 방문하지 않았다면 매칭 시작
if not visited[idx]:
visited[idx] = True
# 매칭하려는 정점에 다른 수가 배정되어 있지 않거나
# 매칭되있는 수를 다른 정점에 배치 가능하다면
if connect[idx] == -1 or bipartite_matching(connect[idx]):
connect[idx] = num
return 1
return 0
# 그룹 2개
# A, B, C, D, E 를 인덱스 0 1 2 3 4 로 사용
alpha = [[2, 5], [2, 3, 4], [1, 5], [1, 2, 5], [2]]
# 전체 매칭 수를 기록할 배열
connect = [-1] * 6
for i in range(5):
# 현재 매칭하며 방문했는지 표시
visited = [False] * 6
bipartite_matching(i)
print(connect)
# =============
# [-1, 3, 0, 1, -1, 2]
728x90
'ALGORITHM > 알고리즘 알아보기' 카테고리의 다른 글
[Algorithm] 세그먼트 트리(Segment Tree) with Python (1) | 2023.05.14 |
---|---|
[Algorithm] CCW 알고리즘 (0) | 2023.03.19 |
[Algorithm] 연쇄 행렬 곱셈(Matrix Chain Multiplication) (0) | 2023.03.03 |
[Algorithm] 냅색 알고리즘 (Knapsack Algorithm) (0) | 2023.01.28 |
[Algorithm] 위상정렬 (0) | 2023.01.28 |