데이터 만들기 6

시간 제한1초메모리 제한128 MB

요약
고정된 규칙에 따라 K개의 삼각형으로 이루어진 가중 방향 그래프와 Q개의 질의를 출력하여, ModifiedDijkstra는 카운터 한계를 넘고 OptimizedBellmanFord는 넘지 않게 만든다.
난이도

보통10점 중 7점

유형
그래프, 최단 경로, 구현, 그리디
정답자
아직 제출이 없습니다

문제

프로그래밍 대회용 문제를 낼 때 가장 어려운 일 중 하나는 테스트 데이터를 만드는 일이다. 좋은 테스트 데이터는 문제의 의도에 맞게 짠 코드와 그렇지 않은 코드를 구별해야 한다.

이 문제는 최단 경로를 구하는 프로그램을 제출하는 문제가 아니다. 두 구현을 구분하는 방향 가중치 그래프를 출력하는 문제이다.

코드 A는 최적화 벨만-포드(OptimizedBellmanFord)이고, 코드 B는 수정 다익스트라(ModifiedDijkstra)이다. 두 코드는 모두 카운터를 유지하며, 카운터가 10610^6을 넘으면 시간 초과이다.

출력할 그래프 XX는 다음을 만족해야 한다.

  1. 코드 A가 XX를 처리할 때 시간 초과가 나면 안 된다.
  2. 코드 B가 XX를 처리할 때 시간 초과가 나야 한다.

아무 그래프나 허용하면 정답이 여러 개이므로, 그래프는 아래 규칙으로 유일하게 정한다.

정수 KK, QQ가 주어지고, 정점 수는 V=2K+1V = 2K+1이다. 정점은 00부터 V−1V-1까지이다.

  • 정점 00은 나가는 변이 없다.
  • 정점 11은 정점 00으로 가는 가중치 11인 변을 하나 가진다.
  • 정점 22는 정점 11로 가는 가중치 11인 변을 하나 가진다.
  • 각 t=1,2,…,K−1t = 1, 2, \ldots, K-1에 대해 다음 삼각형을 붙인다.
    • 정점 2t+12t+1은 정점 2t2t로 가는 가중치 −2t+1-2^{t+1}인 변을 하나 가진다.
    • 정점 2t+22t+2는 나가는 변을 두 개 가진다. 첫 변은 정점 2t+12t+1로 가고 가중치는 2t2^t이다. 둘째 변은 정점 2t2t로 가고 가중치는 00이다.
  • 질의는 QQ개이고, 모두 시작점이 V−1V-1, 도착점이 00이다.

이 그래프는 음수 가중치를 포함한 삼각형을 체인으로 이은 형태이다. 수정 다익스트라는 우선순위 큐에 같은 정점을 지수적으로 여러 번 넣게 되어 KK가 커지면 카운터가 10610^6을 넘는다. 최적화 벨만-포드는 음수 사이클이 없고 정점과 변이 적어 카운터가 한도를 넘지 않는다.

입력

첫째 줄에 정수 KK, QQ가 주어진다.

  • 1≤K≤161 \le K \le 16
  • 1≤Q≤101 \le Q \le 10

출력

그래프와 질의를 아래 형식으로 출력한다. 같은 줄의 정수는 공백 하나로 구분하고, 줄 끝에는 공백을 두지 않는다.

첫째 줄에 VV를 출력한다. V=2K+1V = 2K+1이다.

다음 VV줄 가운데 ii번째 줄(ii는 00부터)에는 정점 ii의 나가는 변 개수 nin_i를 쓰고, 이어서 nin_i개의 쌍 jj ww를 쓴다. jj는 도착 정점이고 ww는 가중치이다.

그다음 줄에 QQ를 출력한다.

다음 QQ줄에 각 질의의 시작점과 도착점을 공백으로 구분해 출력한다.

힌트

최적화 벨만-포드와 수정 다익스트라의 의사코드는 다음과 같다. 카운터는 시간 한도를 재는 값이다.

OptimizedBellmanFord
counter = 0
for each query (s, t):
    dist[u] = INF for all u
    dist[s] = 0
    loop V - 1 times:
        change = false
        for each edge (u, v, w) in adjacency list order:
            counter += 1
            if dist[u] + w < dist[v]:
                dist[v] = dist[u] + w
                change = true
        if change is false:
            break
    output dist[t]
ModifiedDijkstra
counter = 0
for each query (s, t):
    dist[u] = INF for all u
    dist[s] = 0
    pq.push((0, s))
    while pq is not empty:
        counter += 1
        (d, u) = pq.pop()
        if d == dist[u]:
            for each edge (u, v, w):
                if dist[u] + w < dist[v]:
                    dist[v] = dist[u] + w
                    pq.push((dist[v], v))
    output dist[t]

변은 정점 번호가 작은 것부터, 같은 정점에서는 출력에 적은 순서대로 스캔한다. 수정 다익스트라의 우선순위 큐는 (d,u)(d, u)의 최소 힙이다.

예제3

  1. 예제 1

    입력
    1 1
    
    예상 출력
    3
    0
    1 0 1
    1 1 1
    1
    2 0
  2. 예제 2

    입력
    2 1
    
    예상 출력
    5
    0
    1 0 1
    1 1 1
    1 2 -4
    2 3 2 2 0
    1
    4 0
  3. 예제 3

    입력
    3 2
    
    예상 출력
    7
    0
    1 0 1
    1 1 1
    1 2 -4
    2 3 2 2 0
    1 4 -8
    2 5 4 4 0
    2
    6 0
    6 0