알고리즘/BOJ

[BOJ/python]11375번 열혈강호

frog-in-well 2022. 7. 6. 22:47

백준 11375번 열혈강호 파이썬, 네트워크 플로우

출처 - https://www.acmicpc.net/problem/11375

 

11375번: 열혈강호

강호네 회사에는 직원이 N명이 있고, 해야할 일이 M개가 있다. 직원은 1번부터 N번까지 번호가 매겨져 있고, 일은 1번부터 M번까지 번호가 매겨져 있다. 각 직원은 한 개의 일만 할 수 있고, 각각

www.acmicpc.net

네트워크 플로우 연습하고 싶어서 푼 문제였지만 에드몬드 카프로 풀면 시간 초과가 나온다.

덕분에(?) 이분 매칭을 공부할 수 있었다. 네트워크 플로우에 대한 개념을 알고 있었기 때문에 약간의 힌트만 보고 풀 수 있었다.

1. 풀이

sink 노드와 source 노드 없이 직원과 일 노드만 그래프로 표현한다. match 배열을 통해 특정 일이 배정되었음을 표시한다.

  • 모든 직원(node)에 대하여 DFS를 실행한다.
  • 만약 일(next)이 배정되지 않았다면 직원을 일에 배정한다. 이 때 match[next]=node 로 표시한다.
  • 만약 일(next)이 이미 배정되었다면, 해당 일에 배정된 직원(before)을 입력값으로 DFS를 실행한다. 이미 배정되었던 직원(before)이 새로운 일(두번째 재귀에서 next)에 배정된다면 새로운 직원(node)을 일(next)에 배정한다.
    • 만약 이미 배정되었던 직원(before)이 새로운 일에 배정되지 못한 경우(두번째 재귀에서 next)는 pass한다. (ex. before가 오직 next에만 배정 가능한 경우)
  • for문에서 다음 일(next)로 넘어간다. 모든 next에 배정이 불가능하다면 false를 반환한다.

2. 코드

# 열혈강호 (이분매칭)
N,M = map(int, input().split())
path = [ [] for _ in range(N+1) ]
for i in range(N):
    line = list(map(int, input().split()))
    for j in (line[1:]):
        path[i+1].append(j)
        
match = [0 for _ in range(M+1)]    
def DFS(node):
    if visited[node] == 1:
        return False
    
    visited[node]=1
    
    for next in path[node]:
        if match[next] == 0 :
            match[next]=node
            return True
        
        else:
            before = match[next]
            if DFS(before) == True:
                match[next]=node
                return True
            
    return False
    

for i in range(1,N+1):
    visited=[0 for _ in range(N+1)]
    DFS(i)

sol=0
for i in range(M+1):
    if match[i]>0:
        sol+=1
print(sol)