문제
- 문제 링크
BOJ 10623 - Breadth-First Search by Foxpowe
$N$개의 노드로 이루어진 트리가 주어진다.
$1$부터 $BFS$를 진행할 시 방문되는 노드의 순서대로 이동할 때, 총 이동 거리를 계산하자.
TL : $2$ sec, ML : $128$ MB
$1 ≤ N ≤ 10^5$ 루트 노드는 $1$이다.
알고리즘 분류
- 그래프 이론 (graphs)
- 그래프 탐색 (graph_traversal)
- 너비 우선 탐색 (bfs)
- 트리 (trees)
- 최소 공통 조상 (lowest common ancestor)
풀이
어려울 것 없이, 문제의 요구 사항을 그대로 구현해주면 된다.
단, $N ≤ 10^5$ 이므로 이동 거리를 나이브하게 계산할 순 없으니, $LCA$를 이용해 두 노드 사이 거리를 $O(logN)$에 구하도록 하자.
우선 $1$번 노드로부터 $BFS$를 돌려보며 큐에서 꺼내지는 순서대로 기록해두자.
또, 간선의 가중치를 $1$로 잡고 $LCA$를 위한 전처리를 진행하자.
이제 $now = 1$로 잡고, 다음 이동할 정점을 $rec[i]$라 한다면 $dist_{now} + dist_{rec[i]} - 2 * dist_{lca(now, rec[i])}$ 로 이동 거리를 누적할 수 있다.
전체 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #include<bits/stdc++.h> #define N 100001 using namespace std; vector <int> Gr[N]; int dep[N], dist[N], dp[N][18]; int n, rec[N]; void Input() { ios_base::sync_with_stdio(0); cin.tie(0); cin >> n; for (int i(2); i <= n; i++) { int par; cin >> par; Gr[par].push_back(i); } } void BFS() { queue <int> Q; Q.push(1); for (int cnt{}; Q.size();) { int& now(Q.front()); Q.pop(); rec[cnt++] = now; for (int& nxt : Gr[now]) Q.push(nxt); } } void LCAInit(int now, int depth) { dep[now] = depth; for (int& nxt : Gr[now]) if (!dep[nxt]) { dist[nxt] = dist[now] + 1; dp[nxt][0] = now; LCAInit(nxt, depth + 1); } } void TableDP() { for (int j(1); j < 18; j++) for (int i(1); i <= n; i++) dp[i][j] = dp[dp[i][j - 1]][j - 1]; } int getLCA(int x, int y) { if (dep[x] < dep[y]) swap(x, y); int diff(dep[x] - dep[y]); for (int i{}; diff; diff >>= 1, i++) if (diff & 1) x = dp[x][i]; if (x ^ y) { for (int i(17); !!~i; i--) if (dp[x][i] ^ dp[y][i]) x = dp[x][i], y = dp[y][i]; x = dp[x][0]; } return x; } void getAns() { long long ans{}; for (int i(1), now(1); i < n; i++) { int lca(getLCA(now, rec[i])); ans += dist[now] + dist[rec[i]] - 2 * dist[lca]; now = rec[i]; } cout << ans; } int main() { Input(); BFS(); LCAInit(1, 1); TableDP(); getAns(); } | cs |
comment
끝
'Problem Solving > Baekjoon Online Judge (Platinum)' 카테고리의 다른 글
백준 18425 - Putovanje (C++) (2) | 2023.09.28 |
---|---|
백준 23006 - Truck Delivery (C++) (0) | 2023.09.25 |
백준 30092 - 슥삭슥삭 나무자르기 (C++) (1) | 2023.09.25 |
백준 8812 - Jaś Robaczek (C++) (1) | 2023.09.25 |
백준 2849 - 탭댄스 (C++) (0) | 2023.09.11 |