※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 15563번 문제인 Äventyr 1이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/15563
15563번: Äventyr 1
첫 줄에 N과 Q가 입력된다. (1 ≤ N, Q ≤ 105) 둘째 줄에 N - 1개의 시간축 A가 주어지며, 이는 i번째 시간축의 트리 상 부모가 A번째 시간축임을 뜻한다. (i = 2, 3, ..., N, 1 ≤
www.acmicpc.net
15564번 문제에서 트리 대신 배열이 주어진 문제이다.
이 경우, set과 이진탐색을 이용하여 문제를 트리에서보다는 편하게 해결할 수 있다.
글쓴이는 15564번 문제 또한 해결했으므로 해당 코드를 다시 제출하는 것으로 문제를 해결했다.
아래는 제출한 소스코드이다.
#define MAX 1000000007
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int N, Q;
vector<int> G[100001];
int table[100001][17];
int level[100001];
void dfs(int cur, int par, int lv) {
level[cur] = lv;
for (auto& node : G[cur]) {
if (node == par) continue;
dfs(node, cur, lv + 1);
}
}
void tableinit() {
for (int k = 1; k < 17; k++) {
for (int i = 1; i <= N; i++) {
table[i][k] = table[table[i][k - 1]][k - 1];
}
}
}
int dist(int u, int v) {
int ret = 0;
if (level[u] < level[v]) swap(u, v);
int tmp = level[u] - level[v];
int idx = 0;
while (tmp) {
if (tmp & 1) {
ret += (1 << idx);
u = table[u][idx];
}
tmp >>= 1;
idx++;
}
if (u == v) return ret;
for (int k = 16; k > -1; k--) {
if (table[u][k] == table[v][k]) continue;
ret += (1 << k);
ret += (1 << k);
u = table[u][k], v = table[v][k];
}
return ret + 2;
}
bool visited[100001];
int childcnt[100001];
int centroidparent[100001];
int dfs2(int cur, int par) {
int ret = 1;
for (auto& node : G[cur]) {
if (node == par || visited[node]) continue;
ret += dfs2(node, cur);
}
return childcnt[cur] = ret;
}
int centroid(int cur, int par, int K) {
for (auto& node : G[cur]) {
if (node == par || visited[node]) continue;
if (childcnt[node] > K) return centroid(node, cur, K);
}
return cur;
}
void centroid_decomposition(int cur, int par) {
dfs2(cur, 0);
cur = centroid(cur, -1, childcnt[cur] / 2);
centroidparent[cur] = par;
visited[cur] = 1;
for (auto& node : G[cur]) {
if (visited[node]) continue;
centroid_decomposition(node, cur);
}
}
int dp[100001];
void upd(int old) {
int cur = old;
while (cur) {
dp[cur] = min(dp[cur], dist(cur, old));
int par = centroidparent[cur];
cur = par;
}
}
void qry(int old) {
int ret = MAX;
int cur = old;
while (cur) {
ret = min(ret, dp[cur] + dist(old, cur));
int par = centroidparent[cur];
cur = par;
}
if (ret == MAX) cout << -1 << '\n';
else cout << ret << '\n';
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N >> Q;
for (int u = 2; u <= N; u++) {
int v; cin >> v;
G[u].emplace_back(v);
G[v].emplace_back(u);
table[u][0] = v;
}
tableinit();
dfs(1, 0, 1);
centroid_decomposition(1, 0);
for (int i = 1; i <= N; i++) dp[i] = MAX;
while (Q--) {
int q, x; cin >> q >> x;
if (q == 1) upd(x);
else qry(x);
}
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 12024 // C++] 사각형 찾기 (0) | 2022.07.24 |
---|---|
[BOJ 15806 // C++] 영우의 기숙사 청소 (0) | 2022.07.24 |
[BOJ 15805 // C++] 트리 나라 관광 가이드 (0) | 2022.07.24 |
[BOJ 15808 // C++] 주말 여행 계획 (0) | 2022.07.24 |
[BOJ 15804 // C++] 저거 못 타면 지각이야!! (0) | 2022.07.23 |