정확히 \(D\)번 이동한 뒤 시작점(1번 정점)으로 돌아오는 경로(정확히는 walk) 개수를 묻는 문제다.
\(D\)가 최대 \(10^9\)라서 단순 DP는 불가능하고, 인접행렬 거듭제곱으로 해결한다.
문제 정보
문제 링크: https://www.acmicpc.net/problem/14289
문제 요약:
- 정점 \(n\)개(1..n), 무방향 간선 \(m\)개
- 인접 정점으로 이동은 1분, 대기 불가
- \(t=0\)에 1번 정점에서 시작해서, \(t=D\)에 다시 1번 정점에 도착
- 가능한 경로 수를 \(1{,}000{,}000{,}007\)로 나눈 나머지 출력
제한 조건:
- 시간 제한: 2초
- 메모리 제한: 512MB
- \(1 \le n \le 50\)
- \(0 \le m \le 1000\)
- \(1 \le D \le 1{,}000{,}000{,}000\)
입출력 예제
입력 1:
| |
출력 1:
| |
접근 방식
핵심 관찰: 인접행렬의 거듭제곱은 “정확히 k번 이동”의 경로 수를 준다
정점 수가 \(n\)인 그래프의 인접행렬 \(A\)를 다음처럼 정의한다.
- \(A_{i,j} = 1\) if 정점 \(i\)와 \(j\)가 간선으로 연결
- 아니면 \(A_{i,j} = 0\)
그러면 잘 알려진 성질로,
\[ (A^k)_{i,j} = \text{정점 } i \text{에서 출발해 정확히 } k \text{번 이동해 } j \text{에 도착하는 walk 개수} \]따라서 정답은 \((A^D)_{1,1}\) (0-index 기준으로는 \((A^D)_{0,0}\)) 이다.
알고리즘 설계 (Mermaid Flowchart)
flowchart TD
A["입력: n, m, m개의 간선, D"] --> B["A = 인접행렬 구성 (MOD)"]
B --> C["res = I (단위행렬)"]
C --> D{"D > 0 ?"}
D -- "yes" --> E{"D가 홀수?"}
E -- "yes" --> F["res = res * A (MOD)"]
E -- "no" --> G["그대로 진행"]
F --> H["A = A * A (MOD)"]
G --> H
H --> I["D = D // 2"]
I --> D
D -- "no" --> J["출력: res[0][0]"]
구현 포인트
- 입력 순서 주의: 첫 줄에 \(n,m\), 다음 \(m\)줄이 간선, 그 다음 줄이 \(D\)다.
- 오버플로 방지: 곱셈은 최대 \((MOD-1)^2\) 크기까지 커질 수 있으니 C++에서는
__int128로 안전하게 계산한다. - \(n \le 50\)이므로 \(O(n^3 \log D)\) 행렬 거듭제곱이 충분하다.
복잡도 분석
| 항목 | 복잡도 | 비고 |
|---|---|---|
| 시간 복잡도 | \(O(n^3 \log D)\) | 행렬 곱 \(O(n^3)\) × 제곱 횟수 \(O(\log D)\) |
| 공간 복잡도 | \(O(n^2)\) | 인접행렬 및 중간 행렬 저장 |
코너 케이스 및 실수 포인트
| 케이스 | 설명 | 처리 방법 |
|---|---|---|
| m=0 | 간선이 전혀 없는 그래프 | \(D \ge 1\)이면 항상 0 출력 |
| n=1 | 정점이 1개뿐 | 간선이 없으므로 \(D \ge 1\)이면 0 |
| D가 매우 큼 | \(10^9\) | 빠른 거듭제곱으로 처리 |
| 곱셈 오버플로 | long long만으로는 위험 | __int128로 (x*y)%MOD 계산 |
| 입력 파싱 실수 | \(D\)를 첫 줄로 읽으면 오답/RE | \(n,m\) 후 간선 \(m\)줄, 마지막에 \(D\) |
구현 코드 (C++)
| |
![Featured image of post [Algorithm] C++ 백준 14289번: 본대 산책 3](/post/algorithm/2026-01-02-boj-14289-bondae-walk-3-matrix-exponentiation-cpp-solution/wordcloud_hu_30e1c67b8600f852.png)
![[Algorithm] C++ 백준 18874번: Haircut](/post/algorithm/2026-01-05-boj-18874-haircut-fenwick-tree-inversion-cpp-solution/wordcloud_hu_f1156fbd3412a468.png)
![[Algorithm] C++ 백준 9120번: Oulipo 다국어](/post/algorithm/2026-01-05-boj-9120-oulipo-multilingual-kmp-string-matching-cpp-solution/wordcloud_hu_cabf7853c1ed85cc.png)
![[Algorithm] C++ 백준 14289번: 본대 산책 3](/post/algorithm/2026-01-02-boj-14289-bondae-walk-3-matrix-exponentiation-cpp-solution/wordcloud_hu_ae0f59803f116fbf.png)
![[Algorithm] C++ 백준 12012번: Closing the Farm (Gold)](/post/algorithm/2025-12-23-boj-12012-closing-the-farm-dsu-offline-cpp-solution/wordcloud_hu_5a95d85e90d9352c.png)
![[Algorithm] C++ 백준 1258번: 문제 할당](/post/algorithm/2025-12-23-boj-1258-problem-assignment-hungarian-cpp-solution/wordcloud_hu_fb5f370a4bccc9ee.png)
![[Algorithm] C++ 백준 2988번: 아보가드로](/post/algorithm/2025-12-19-boj-2988-avogadro-cpp-solution/wordcloud_hu_504f3f1bc728ef52.png)
![[Algorithm] C++ 백준 12850번 본대 산책2](/post/algorithm/2025-12-04-boj-12850-campus-walk-matrix-exponentiation-cpp-solution/wordcloud_hu_6f8f9e4e82600159.png)
![[Algorithm] C++ 백준 13232번: Domain clusters](/post/algorithm/2025-12-22-boj-13232-domain-clusters-scc-tarjan-cpp-solution/wordcloud_hu_3a7a8d5f138b64d1.png)
![[Algorithm] C++ 백준 25201번: 보드 뒤집기 게임](/post/algorithm/2025-12-19-boj-25201-board-flipping-game-cpp-solution/wordcloud_hu_22b1d8c414e9b6d9.png)