K 와 H 를 막는 최소 컷을 구하는 것이 문제이다. 우리는 최대 유량 최소 컷 정리를 통해서 최대유량을 구하면 된다는 것을 알 수 있다. 이때 우리가 원하는건 정점인 벽을 최소한으로 없애는거지 간선의 수를 최소한으로 없애는 것이 아니다. 그러므로 정점 분할을 시도하여 정점을 간선으로 만들고 In->Out 의 Capacity 를 1 로 설정해야 한다. 그러면 간선이 아니라 정점을 최소한으로 막는 문제가 된다.
정점 분할을 시도하는 경우 기존의 정점 간의 간선의 Capacity 를 보통 무한대 값을 둔다. 여기서는 어차피 정점 분할로 정점 간 1 이상 흐르지 못하기 때문에 1로 둬도 상관없다.
시간복잡도에 대해서
100x100==10000 개의 정점에 간선이 대략 40000 개인데 에드몬크 카프 기준으로 어떻게 통과할 수 있을까? 이는 최대 흐름이 4로 (좌우상하를 막으면 되므로) 고정되어 있음을 생각하면 간단히 알 수 있다. 에드몬드 카프에서 Augmenting Path 에 대해 증가연산을 최대 \((\vert V \vert \vert E \vert)\) 번 하던 것이 4개로 줄기 때문에 증가연산을 위한 비용인 BFS 에 해당하는 O(\(\vert E\vert\)) 만 남기 때문이다.
관계행렬을 쓰면 메모리가 부족함
또 다른 문제는 메모리인데, 정점 당 5개의 간선만 (좌우상하 + 정점 분할용 간선) 가지는 걸 활용하면 정점->정점 의 관계를 (정점, 방향)->정점 으로 바꾸어 공간복잡도를 O(\(4NM\)) 으로 줄일 수 있다. 압축용 알고리즘은 Tricky 한데, 정점분할로 In-Out 으로 분리된 정점은 In 과 Out 간에만 연결이 되는 것과, 방향에 1,2,3,4 를 적당히 주면 5-dir 가 반대편 방향이 되는 것을 이용했다.
그냥 속편하게 unordered_map<int, unordered_map<int, int>> 를 사용해도 된다.
댓글남기기