※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 25198번 문제인 곰곰이의 심부름이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/25198
25198번: 곰곰이의 심부름
곰곰이의 이동 경로는 $1 \rightarrow 2 \rightarrow 3 \rightarrow 5 \rightarrow 3 \rightarrow 4$ 이고, 나올 수 있는 순서쌍은 $(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (5, 3), (5, 4)$이다.
www.acmicpc.net
중간지점인 C를 기준으로, C에서 S, C에서 H로 가는 경로들을 각각 LS, LH라 하자.
LS와 LH의 공통노드 중 C에서 가장 먼 노드를 X라 할 때, 문제의 경로는 "S에서 X이전까지", "X에서 C를 찍고 다시 X까지", "X 다음서부터 H까지"의 세 부분으로 나눌 수 있다. 이러한 X는 C를 루트로 하는 트리에서의 S와 H의 LCA로 구해낼 수 있다.
각 부분의 노드 개수를 이용하여 답을 계산해내자.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
vector<int> G[100001];
int level[100001];
int par[100001];
void dfs(int cur) {
for (auto& node : G[cur]) {
if (level[node]) continue;
level[node] = level[cur] + 1;
par[node] = cur;
dfs(node);
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int N; cin >> N;
int S, C, H; cin >> S >> C >> H;
for (int i = 1; i < N; i++) {
int u, v; cin >> u >> v;
G[u].emplace_back(v);
G[v].emplace_back(u);
}
level[C] = 1;
dfs(C);
if (level[S] < level[H]) swap(S, H);
ll cntS = level[S], cntH = level[H];
ll tmpS = cntS, tmpH = cntH;
while (tmpS > tmpH) {
S = par[S];
tmpS--;
}
while (S != H) {
tmpS--; tmpH--;
S = par[S];
H = par[H];
}
ll cntLCA = level[S];
cntS -= cntLCA, cntH -= cntLCA;
cout << cntLCA * (cntLCA - 1) + (cntS + cntH) * cntLCA + cntS * cntH + (cntS * (cntS - 1)) / 2 + (cntH * (cntH - 1)) / 2;
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 25201 // C++] 보드 뒤집기 게임 (0) | 2022.05.15 |
---|---|
[BOJ 25197 // C++] 합주단 곰곰 (0) | 2022.05.15 |
[BOJ 25192 // C++] 인사성 밝은 곰곰이 (0) | 2022.05.15 |
[BOJ 25199 // C++] 도박사 곰곰 (0) | 2022.05.15 |
[BOJ 25194 // C++] 결전의 금요일 (0) | 2022.05.15 |