문제


https://www.acmicpc.net/problem/1420


풀이


우선 현재 위치와 학교가 인접할 때만 학교에 가는 것을 막을 수 없다.

그렇지 않다면, 현재 위치를 source로 하고, 학교를 sink로 하며, 각 위치에 정점 분할 (in -> out)을 적용한 flow network를 구상한다.

이때 MFMC theorem을 이용하면, 최대 유량이 정답이 된다.


코드


import sys
from collections import deque

n, m = map(int, sys.stdin.readline().split())
board = [sys.stdin.readline().strip() for _ in range(n)]
graph = [[] for _ in range(2 * n * m)]

for i in range(n):
    for j in range(m):
        if board[i][j] == '#':
            continue

        if board[i][j] == 'K':
            x, y = i, j
            start = m * i + j + m * n
        
        elif board[i][j] == 'H':
            z, w = i, j
            end = m * i + j
            continue

        graph[m * i + j].append(m * i + j + m * n)
        
        if i and (board[i - 1][j] not in 'K#'):
            graph[m * i + j + m * n].append(m * (i - 1) + j)
        
        if (i < n - 1) and (board[i + 1][j] not in 'K#'):
            graph[m * i + j + m * n].append(m * (i + 1) + j)
        
        if j and (board[i][j - 1] not in 'K#'):
            graph[m * i + j + m * n].append(m * i + j - 1)
        
        if (j < m - 1) and (board[i][j + 1] not in 'K#'):
            graph[m * i + j + m * n].append(m * i + j + 1)

if abs(x - z) + abs(y - w) == 1:
    print(-1)
    exit()

ans = 0
while True:
    prev = [-1] * (2 * n * m)
    queue = deque([start])
    while queue:
        cur = queue.popleft()
        
        for nxt in graph[cur]:
            if nxt == end:
                prev[end] = cur
                break
            
            if prev[nxt] == -1:
                prev[nxt] = cur
                queue.append(nxt)

        if prev[end] != -1:
            break
    
    if prev[end] == -1:
        break

    ans += 1
    nxt = end
    while True:
        cur = prev[nxt]
        graph[cur].remove(nxt)
        graph[nxt].append(cur)
        nxt = cur
        if nxt == start:
            break

print(ans)

Leave a comment