728x90
#11375 열혈강호 https://www.acmicpc.net/problem/11375
처음엔 열심히 풀었다.
틀린 코드
n, m = map(int, input().split())
people = {x: [] for x in range(1, n + 1)}
for i in range(1, n + 1):
tmp = list(map(int, input().split()))
if tmp[0]:
people[i] = tmp[1:]
works = [0] * (m + 1) # 인덱스 1부터 사용
# print(people)
def allocate(idx):
# input()
target = people[idx]
if len(target):
# 1. 가장 첫 번째 일에 연결
for w in target:
# hidden
if works[w] == idx:
continue
# print(idx, w)
if works[w] == 0: # 2-1. 연결되지 않은 상태일 경우
works[w] = idx # 2-1-1. 현재 작업자를 연결
return # 2-2-2. 연결 성공 시 종료
else: # 2-2. 연결된 상태일 경우
prev = works[w]
allocate(prev) # 2-2-1. 기존의 작업자를 이동
if works[w]: # 2-2-2. 기존 작업자의 이동이 불가한 경우
continue # 2-2-2-1. 현재 작업자의 다음 일로, 2번부터 진행
else: # 2-2-3. 기존 작업자의 이동이 가능한 경우
works[w] = idx # 2-2-3-1. 연결
return # 2-2-3-2. 연결 성공 시 종료
# 3. 이를 반복하고, 할당 가능한 일이 없는 경우, 포기. 현재 작업자를 버림.
for i in range(1, n + 1):
allocate(i)
# print(people)
print(sum(map(lambda x: x > 0, works)))
논리적 사고 흐름을 그대로 옮겨 구현한 방식인데, 재귀 호출 횟수가 너무 많았다.
알고리즘 분류를 보니 "이분 매칭"이었다.
음... 이분 탐색도 아니고 이분 매칭이라니...
내가 모르는 알고리즘이 나오기 시작한다. 이게 플레티넘?
열심히 학습했다.
생각보다 단순해서 정말 놀랐다.
처음 이해하는 데 있어서 조금 버거웠지만,
이해해보니 DFS와 크게 다르지 않았다.
https://yjg-lab.tistory.com/209
[알고리즘] 이분 매칭 알고리즘 (Bipartite Matching)
이분 매칭 알고리즘 (Bipartite Matching) 두 개의 정점 그룹이 존재할 때 모든 간선(경로)의 용량이 1이면서 양쪽 정점이 서로 다른 그룹에 속하는 그래프를 이분 그래프(Bipartite Graph)라고 말합니다.
yjg-lab.tistory.com
정답코드
import sys
sys.setrecursionlimit(1000 * 1000)
input = sys.stdin.readline
n, m = map(int, input().split())
people = {x: [] for x in range(1, n + 1)}
for i in range(1, n + 1):
tmp = list(map(int, input().split()))
if tmp[0]:
people[i] = tmp[1:]
visited = [False] * (m + 1) # 인덱스 1부터 사용. 방문기록
workers = [0] * (m + 1) # 인덱스 1부터 사용. 각 인덱스를 누가 처리하기로 했는지를 기록
# print(people)
def allocate(idx):
for i in range(len(people[idx])): # 가능한 일을 모두 순회
now = people[idx][i]
if visited[now]: # 방문한 일이면 무시
continue
else: # 방문하지 않은 일이면 진행
visited[now] = True # 방문처리
if workers[now] == 0 or allocate(workers[now]):
workers[now] = idx
return True
return False
for idx in range(1, n + 1):
visited = [False] * (m + 1)
if n == sum(map(lambda x: x > 0, workers)):
print(n)
exit()
else:
allocate(idx)
# print(people)
print(sum(map(lambda x: x > 0, workers)))
이제 이분 매칭 문제는 다 풀 수 있을 것 같다.
'Algorithm > acmicpc.net' 카테고리의 다른 글
실버는 선녀야 (#13305 주유소) (0) | 2024.10.15 |
---|---|
아니 이걸 어떻게 풀어 (#1708 볼록 껍질) (3) | 2024.10.15 |
두 개의 변량을 반영한 값을 만든다면 (#9251) (0) | 2024.10.13 |
트리의 지름을 구하는게 공식이 있다니... (#1167) (2) | 2024.10.10 |
dp를 2차원으로 확장시켜야... (#12865) (5) | 2024.10.09 |