이 문제는 격자 위에 놓인 \(N\)개의 블록(채워진 셀)로 이루어진 “도시”가 구멍 없이 연결되어 있을 때,
블록 그래프(상하좌우 인접)에서 모든 블록 쌍 최단거리의 합을 \(10^9\)로 나눈 값을 구하는 문제다.
핵심은 격자 그래프에서 모든 쌍을 직접 BFS/플로이드로 처리하는 대신, 도시를 행/열의 연속 구간으로 압축해
두 개의 가중 트리로 바꾸고, 트리의 간선 기여를 합산하는 것이다.
문제 정보
문제 요약:
- \(N\)개의 블록 좌표 \((X[i], Y[i])\)가 주어진다.
- 두 블록이 상하좌우로 인접하면 간선이 있는 그래프를 생각한다.
- 도시가 “이상적”이라는 조건은 다음을 의미한다.
- 채워진 셀(블록)들이 모두 연결
- 비어 있는 셀들도 모두 연결 (즉, 블록들이 격자 평면을 “구멍 없이” 채운 폴리오미노 형태)
- 모든 \(0 \le i < j \le N-1\)에 대해 최단거리 \(d(v_i, v_j)\)의 합을 구해 \(10^9\)로 나눈다.
제한 조건:
- 시간 제한: 1초
- 메모리 제한: 256MB
- \(N \le 100{,}000\)
- 좌표 범위는 매우 크지만(최대 \(2^{31}-2\)), 실제로 주어지는 블록 개수만 \(N\)개다.
입출력 예제
입력 1:
| |
출력 1:
| |
접근 방식
핵심 관찰 1: “행 연속 구간”과 “열 연속 구간”으로 압축
각 행 \(r\)에서 블록들이 놓인 열들을 정렬하면, 연속한 열들(\(y, y+1, y+2, \dots\))이 연결된 그룹을 이룬다.
이 그룹 하나를 “행 구간 노드”로 만들고, 그 노드의 가중치는 구간 길이(셀 개수)로 둔다.
마찬가지로 각 열 \(c\)에서 블록들이 놓인 행들을 정렬해 “열 구간 노드”를 만들고 가중치를 둔다.
핵심 관찰 2: 압축하면 두 개의 트리가 된다 (IOI 2012 공식 해법 아이디어)
도시가 구멍 없이 연결되어 있으면, 다음 구조가 성립한다.
- 행 구간 노드들 사이: 세로 인접(위아래)로 인해 연결이 생긴다.
- 열 구간 노드들 사이: 가로 인접(좌우)로 인해 연결이 생긴다.
이렇게 만들면:
- 행 구간 노드 그래프 \(T_H\) (horizontal segments tree)
- 열 구간 노드 그래프 \(T_V\) (vertical segments tree)
가 각각 트리가 된다.
핵심 관찰 3: 최단거리의 합은 “두 트리 거리 합”으로 분해된다
임의의 두 셀 사이 최단경로는 “세로 이동 성분” + “가로 이동 성분”으로 분해할 수 있고, 전체 거리 합도 다음처럼 분해된다.
- \(T_H\)에서의 거리 기여(세로 인접을 통해 행 구간이 바뀌는 횟수)
- \(T_V\)에서의 거리 기여(가로 인접을 통해 열 구간이 바뀌는 횟수)
결국 우리가 원하는 값은:
- \(T_H\)에서 모든 노드쌍 \((x,y)\)에 대해 \(w(x)w(y)\,d_{T_H}(x,y)\)의 합
- \(T_V\)에서 동일한 합
의 합이다. (여기서 \(w(\cdot)\)는 구간 길이)
핵심 관찰 4: 트리의 모든 쌍 거리 가중합은 “간선 절단 기여”로 O(E)에 계산
트리 \(T\)에서 다음 값을 생각하자:
\[ \sum_{x간선 \(e\)를 제거해 트리가 두 컴포넌트로 나뉠 때, 각 컴포넌트의 가중치 합을 \(S(e)\), \(S'(e)\)라 하면, 그 간선을 “지나는” 쌍은 정확히 \(S(e)\cdot S'(e)\)개(가중치 기준)이고, 따라서 전체 합은:
\[ \sum_{e \in T} S(e)\,S'(e) \]가 된다.
이 값은 루트를 잡고 서브트리 합을 구하면 선형 시간에 계산 가능하다.
알고리즘 설계 (Mermaid Flowchart)
flowchart TD
A["입력 N, 좌표 (X[i], Y[i])"] --> B["행별/열별로 인덱스 그룹화"]
B --> C["각 행에서 연속한 열들을 묶어행 구간 노드 생성 (가중치=길이)"]
B --> D["각 열에서 연속한 행들을 묶어열 구간 노드 생성 (가중치=길이)"]
C --> E["세로 인접( x+1, y )를 이용해행 구간 트리 T_H 간선 구성"]
D --> F["가로 인접( x, y+1 )를 이용해열 구간 트리 T_V 간선 구성"]
E --> G["T_H에서 서브트리 합으로Σ S(e)*S'(e) 계산"]
F --> H["T_V에서 서브트리 합으로Σ S(e)*S'(e) 계산"]
G --> I["(G+H) mod 1e9 출력"]
H --> I
복잡도 분석
| 항목 | 복잡도 | 비고 |
|---|---|---|
| 시간 복잡도 | \(O(N \log N)\) | 행/열별 정렬이 지배 |
| 공간 복잡도 | \(O(N)\) | 해시맵 + 구간/간선 저장 |
코너 케이스 및 실수 포인트
| 케이스 | 설명 | 처리 방법 |
|---|---|---|
| 좌표가 매우 큼 | 격자 전체를 만들 수 없음 | 좌표→인덱스 해시맵 사용 |
| 중복 간선 | 인접한 여러 셀이 같은 구간쌍을 잇는 경우 | 간선은 집합으로 중복 제거 |
| 큰 합 | \(\Theta(N^3)\) 수준까지 커질 수 있음 | long long + 모듈러 |
| 트리가 여러 컴포넌트? | 이상적인 도시라면 트리/연결 보장 | 구현은 포레스트도 처리 가능하게 작성 |
구현 코드
C++
| |
![Featured image of post [Algorithm] C++ 백준 5813번: 이상적인 도시](/post/algorithm/2025-12-19-boj-5813-ideal-city-cpp-solution/wordcloud_hu_df4650bb3305adcd.png)
![[Algorithm] C++ 백준 3948번: 홍준이의 친위대](/post/algorithm/2025-12-19-boj-3948-hongjuns-royal-guards-cpp-solution/wordcloud_hu_72c9c02c1d626af1.png)
![[Algorithm] C++ 백준 5498번: Batch Scheduling](/post/algorithm/2025-12-19-boj-5498-batch-scheduling-cpp-solution/wordcloud_hu_ea128457d0ff4d1c.png)
![[Algorithm] C++ 백준 5813번: 이상적인 도시](/post/algorithm/2025-12-19-boj-5813-ideal-city-cpp-solution/wordcloud_hu_8653825e20480456.png)
![[Algorithm] C++ 백준 6223번: Cow Sorting](/post/algorithm/2025-12-19-boj-6223-cow-sorting-cpp-solution/wordcloud_hu_f6ecf74bd68c4451.png)
![[Algorithm] C++ 백준 7727번: Byephone](/post/algorithm/2025-12-19-boj-7727-byephone-hirschberg-lcs-cpp-solution/wordcloud_hu_7264c733e5d43dbc.png)
![[Algorithm] C++ 백준 1185번: 유럽여행](/post/algorithm/2025-12-19-boj-1185-europe-travel-mst-kruskal-cpp-solution/wordcloud_hu_a7973902548ef27b.png)
![[Algorithm] C++ 백준 20506번: Kaisar - 생존](/post/algorithm/2025-12-19-boj-20506-kaisar-survival-cpp-solution/wordcloud_hu_1115df393a79effd.png)
![[Algorithm] C++ 백준 11933번: 공장들](/post/algorithm/2025-08-14-boj-11933-factories-virtual-tree-lca-cpp-solution/wordcloud_hu_12426b454432f618.png)
![[Algorithm] C++ 백준 16074번: Mountaineers - Minimax MST·LCA](/post/algorithm/2025-08-14-boj-16074-mountaineers-minimax-mst-union-find-lca-cpp-solution/wordcloud_hu_d420ce5a298846ed.png)
![[Algorithm] C++ 백준 13539번: 트리와 쿼리 11](/post/algorithm/2025-12-19-boj-13539-tree-and-query-11-link-cut-tree-cpp-solution/wordcloud_hu_22549d9781144aba.png)