문제
풀이
인접하지 않은 두 회사를 케이블로 잇는 것은 손해라는 것을 자명하게 알 수 있습니다.
따라서 홀수번째 회사에서 짝수번째 회사로 가는 용량 1짜리의 간선을 잇고 최소 비용 최대 유량 알고리즘으로 해결할 수 있습니다.
다만 회사의 수가 너무 크므로 최적화가 필요합니다.
음의 유량 아이디어는 보낸 유량을 회수하고 다른 곳으로 보내는 아이디어입니다. 이 아이디어를 이용해서 그리디 알고리즘으로 해결할 수 있습니다.
먼저 우선순위 큐를 만들고 큐에 모든 간선 $(i, i + 1)$을 넣습니다. 큐에 담긴 간선 $(i, j)$의 가중치는 회사 $i$와 $j$를 선택하기 위한 비용이라고 생각하면 됩니다.
큐에서 가중치가 가장 작은 간선 $(i, i + 1)$을 꺼내고 답에 가중치를 더합니다. $i$번째 회사와 $i + 1$번째 회사는 더 이상 다른 회사와 이어질 수 없으므로 두 회사와 이어진 간선을 우선순위 큐에서 제거해야 합니다.
간선 $(i - 1, i)$와 $(i + 1, i + 2)$를 큐에서 실시간으로 제거하는 대신 $i$와 $i + 1$가 선택되었는지 기록한 다음 나중에 해당되는 간선을 큐에서 뽑았을 경우 continue하는 방식으로 구현하면 됩니다.
$(i, i + 1)$ 대신 다른 간선을 잇는 것이 이득인 경우를 고려하기 위해서 $(i - 1, i)$와 $(i + 1, i + 2)$의 가중치를 더한 값에 $(i, i + 1)$의 가중치를 뺀 간선 $(i - 1, i + 2)$를 큐에 새로 넣어줍니다.
두 간선 $(i - 1, i)$와 $(i + 1, i + 2)$ 중 하나만 사용하는 경우는 가중치가 가장 작은 것 부터 고른다는 알고리즘에 의해서 둘 모두를 고르는 것보다 손해임을 알 수 있습니다.
이때 큐에 새로 넣은 간선 $(i - 1, i + 2)$를 또 회수하고 다른 간선으로 잇는 게 이득인 경우도 생길 수 있습니다. 따라서 간선을 큐에서 꺼낼 때 마다 회사의 왼쪽, 오른쪽에 아직 점유되지 않은 가장 가까운 회사의 번호와 그 회사를 고르기 위한 비용을 기록해 주어야 합니다.
코드
1 | |