BOJ 27180 Тяжелый груз

BOJ 27180 Тяжелый груз

문제 링크:

문제 내용

당신은 어떤 창고에서 특별한 리프트를 이용해서 거대한 상자를 옮기려고 합니다. 이 창고는 nn개의 방과 mm개의 복도로 이루어져 있으며, 각 방에는 1부터 nn까지의 서로 다른 번호가 붙어 있습니다. 각각의 복도는 서로 다른 두 방을 연결하며, 모든 복도를 통해서 양방향으로 이동할 수 있습니다.

거대한 상자는 처음에 1번 방에 있으며, 리프트 위에 올려져 있습니다. 당신은 상자를 옮기기 위해 다음과 같은 행동을 할 수 있습니다.

  • ii번 방에서 리프트 위에 상자가 올려져 있을 때, ii번 방에서 하나의 복도로 연결된 jj번 방에 상자를 내려놓을 수 있습니다. 리프트는 ii번 방에 그대로 있습니다. 이 행동의 비용은 1입니다.
  • ii번 방에 상자가 놓여 있고 ii번 방에서 하나의 복도로 연결된 jj번 방에 리프트가 있을 때, 상자를 들어올릴 수 있습니다. 리프트와 상자는 jj번 방에 있게 됩니다. 이 행동의 비용은 1입니다.
  • ii번 방에 상자가 놓여 있고 jj(iji \neq j)번 방에 리프트가 있을 때, jj번 방에서 하나의 복도로 연결된 kk번 방으로 리프트를 이동할 수 있습니다. kk번 방에 상자가 있다면 이동할 수 없습니다. 이 행동의 비용은 0입니다.

1번 방을 제외한 2,3,,n2, 3, \cdots, n번 방에 리프트 위에 상자가 올려져 있도록 하기 위해 필요한 최소 비용을 구하세요.

입력

첫 번째 줄에는 테스트 케이스의 개수 TT가 주어집니다. (1T100  0001 \le T \le 100\;000)

각 테스트 케이스에 대해, 첫 번째 줄에 nnmm이 주어집니다. (2n500  0002 \le n \le 500\;000, 1m500  0001 \le m \le 500\;000)

다음 mm줄에 걸쳐서 ii번째 줄에는 ii번째 복도가 잇는 두 방의 번호 uiu_iviv_i가 주어집니다. (1ui,vin1 \le u_i, v_i \le n, uiviu_i \neq v_i)

주어지는 그래프는 단순 연결 그래프이며, nnmm의 총합은 각각 500  000500\;000을 초과하지 않습니다.

출력

각 테스트 케이스에 대해, 2,3,,n2, 3, \cdots, n번 방으로 상자와 리프트를 옮기는 데 필요한 최소 비용을 순서대로 한 줄에 출력합니다. ii번 방에 대해, 어떻게 옮겨도 ii번 방으로 옮길 수 없다면 -1을 대신 출력합니다.

문제 풀이

스포일러

주어진 그래프에서 BCC들을 계산합니다. 그러면 다음과 같은 관찰을 할 수 있습니다.

  • 상자가 ii번 방에 있을 때 ii번 방이 단절점이면, 리프트는 ii번 방에 이웃한 방들 중 다른 BCC에 속한 방으로 이동할 수 없습니다.
  • 따라서, 상자와 리프트를 다른 BCC로 이동하는 유일한 방법은 리프트와 상자가 동시에 단절점에 오도록 하는 것입니다.
  • 하나의 BCC 내에서는 상자가 어디에 있든 리프트를 항상 원하는 곳으로 옮길 수 있습니다.

이를 이용하여, 다음과 같이 BCC별로 BFS를 돌리는 방법을 생각할 수 있습니다.

  • 현재의 상태를 (상자의 위치, 상자가 리프트 위에 있는지 여부)로 나타냅니다.
  • 현재의 BCC 내에서 BFS를 돌립니다. 이때 상자가 이웃한 방으로 이동할 때마다 거리가 1 증가하고, 상자가 리프트 위에 있는지 여부가 바뀝니다.
  • 현재의 BCC에 속한 점들 중 단절점 ii에 대해, (ii, true)가 도달 가능하다면, ii를 포함하는 다른 BCC들에 대해 탐색을 반복합니다.
    • 이때 새로운 BCC에서의 초기 조건은 (ii, true)의 거리를 그대로 두고, (ii, false)의 거리를 무한으로 다시 바꿔야 합니다. 이전 BCC에서의 (ii, false)와 현재 BCC에서의 (ii, false)는 호환되지 않기 때문입니다.

이를 총 시간 복잡도 O(n+m)\mathcal{O}(n + m)이 되도록 잘 구현하면 됩니다.

Last updated on