최단 경로 테스트 데이터 만들기
시간 제한1초메모리 제한128 MB
정해진 최단 경로 테스트 그래프를 출력한다. 체인과 0번 정점의 자기 루프 개수를 계산해 넣고, V-1에서 0으로 가는 질의 Q개를 붙인다.
문제
프로그래밍 대회용 그래프 문제를 내려면, 의도한 해법은 통과하고 느린 해법은 시간 초과가 나도록 테스트 데이터를 만들어야 한다. 이 문제는 그런 데이터를 출력한다. 조건을 만족하는 데이터가 여러 개일 수 있으므로, 아래에서 정한 구성만 출력한다.
대상은 가중치 있는 유향 그래프의 최단 경로이다. 정점 번호는 부터 까지이다. 질의 에 대해 에서 로 가는 최단 경로의 가중치 합을 라 한다. 도달할 수 없으면 이다.
두 구현의 시간 초과는 코드 안의 counter가 을 넘는 것으로 판정한다.
플로이드-워셜은 인접 행렬에서 아래를 수행하므로 counter는 항상 이다. 이면 시간 초과가 아니다.
counter = 0
for k = 0 to V-1:
for i = 0 to V-1:
for j = 0 to V-1:
counter += 1
M[i][j] = min(M[i][j], M[i][k] + M[k][j])
최적화된 벨만-포드는 각 질의마다 거리를 초기화한 다음, 인접 리스트의 모든 간선을 최대 라운드 완화한다. 정점은 번부터 번 순서로 본다. 한 라운드에서 갱신이 없으면 즉시 중단한다. counter는 간선을 볼 때마다 증가한다.
counter = 0
for each query (s, t):
set dist[v] = 10^9 for every vertex v
dist[s] = 0
repeat V-1 times:
change = false
for each edge (u, v) in adjacency-list order:
counter += 1
if dist[u] + weight(u, v) < dist[v]:
dist[v] = dist[u] + weight(u, v)
change = true
if change is false:
break
출력할 그래프는 다음으로 유일하게 정한다.
정점 개를 로 둔다. 각 에 대해 정점 에서 정점 로 가는 가중치 인 간선을 하나 둔다. 정점 에는 가중치 인 자기 루프를 개 둔다. 는 다음을 모두 만족하는 가장 큰 음이 아닌 정수이다.
- 간선 수 가 이하이다.
- 출력에 들어가는 정수의 개수 가 이하이다.
질의는 개이고, 모두 시작점이 , 끝점이 이다.
이 구성에서 플로이드-워셜의 counter는 이다. 최적화된 벨만-포드는 매 라운드 체인을 한 칸만 완화하므로 라운드를 모두 수행하고, counter는 이다. , , 이면 플로이드-워셜은 시간 초과가 아니고 최적화된 벨만-포드는 시간 초과이다.
입력
첫째 줄에 정점 수 , 질의 수 , 정수 개수 상한 가 공백으로 구분되어 주어진다.
출력
최단 경로 문제의 입력 형식 그대로 출력한다.
첫째 줄에 를 출력한다.
다음 줄에는 정점 부터 까지 나가는 간선을 출력한다. 각 줄의 첫 수는 나가는 간선 수 이고, 그 뒤에 개의 정수 쌍 가 온다. 는 도착 정점, 는 가중치이다.
- 정점 : 이고, 개의 쌍은 모두 이다.
- 정점 (): 이고, 쌍은 이다.
그 다음 줄에 를 출력한다.
다음 줄에 각 질의의 시작점과 끝점을 출력한다. 모든 줄은 이다.
한 줄에서 인접한 두 정수 사이에는 공백 하나를 둔다. 줄 끝에 공백을 두지 않는다.
힌트
출력에 들어가는 정수는 다음과 같이 센다. 한 개, 각 정점의 를 합한 개, 각 간선의 를 합한 개, 한 개, 각 질의의 를 합한 개이다. 따라서 이고, 를 대입하면 이다.
그래프는 다음도 만족해야 한다. 간선 가중치의 절댓값은 미만이고, 질의의 시작점에서 도달 가능한 음수 사이클은 없다. 위 구성은 가중치가 모두 이므로 이 조건을 지킨다.
자기 루프의 가중치가 양수이면, 정점 을 자기 루프로 갱신하는 일은 일어나지 않는다. 체인 만 매 라운드 한 칸씩 완화된다.