티스토리 뷰

BOJ

[BOJ 1761] 정점들의 거리

gcmango 2021. 5. 12. 14:29

문제

www.acmicpc.net/problem/1761

 

1761번: 정점들의 거리

첫째 줄에 노드의 개수 N이 입력되고 다음 N-1개의 줄에 트리 상에 연결된 두 점과 거리를 입력받는다. 그 다음 줄에 M이 주어지고, 다음 M개의 줄에 거리를 알고 싶은 노드 쌍이 한 줄에 한 쌍씩

www.acmicpc.net

 


풀이

LCA(Lowest Common Ancestor)를 사용합니다.

먼저, 다음 4개의 배열을 만듭니다:

 

  • \(graph[i][j].x,\ graph[i][j].y:\) \(i\)의 \(j\)번째 자식 노드와 그 노드까지의 거리.
  • \(par[i][j]:\) \(i\)의 \(2^j\)번째 조상.
  • \(depth[i]:\) \(i\)의 깊이.
  • \(dist[i]:\) 루트로부터 \(i\)까지의 거리.

트리를 순회하면서 각 노드마다 위의 정보를 저장해줍니다.

 

다음으로, 입력받은 각 쌍 \((a_{i}, b_{i})\)에 대해 두 노드의 \(lca\)를 구해준 다음,

\(dist[a_{i}]+dist[b_{i}]\)에서 공통부분인 \(dist[lca]\) 부분을 빼주면 답을 알 수 있습니다.

 


코드

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;

typedef long long ll;
typedef pair<int, int> p;
const int MAX_LVL = (int)floor(log2(40000));

int N, M;
vector<vector<p>> graph;
vector<vector<int>> par;
vector<int> depth;
vector<int> dist;

void solve(int cur, int pnode) {
    for (int i = 1; i <= MAX_LVL; ++i)
        par[cur][i] = par[par[cur][i - 1]][i - 1];

    for (auto next : graph[cur]) {
        if (next.x != pnode) {
            depth[next.x] = depth[cur] + 1;
            par[next.x][0] = cur;
            dist[next.x] = dist[cur] + next.y;
            solve(next.x, cur);
        }
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> N;
    graph.resize(N + 1);
    par.resize(N + 1, vector<int>(MAX_LVL + 1));
    depth.resize(N + 1, 0);
    dist.resize(N + 1);

    for (int i = 0; i < N - 1; ++i) {
        int a, b, c;
        cin >> a >> b >> c;
        graph[a].push_back({b, c});
        graph[b].push_back({a, c});
    }

    solve(1, 0);

    cin >> M;
    while (M--) {
        int a, b;
        cin >> a >> b;
        int ans_x = dist[a], ans_y = dist[b];
        if (depth[a] != depth[b]) {
            if (depth[a] >= depth[b])
                swap(a, b);

            for (int i = MAX_LVL; i >= 0; --i)
                if (depth[a] <= depth[par[b][i]])
                    b = par[b][i];
        }

        int lca = a;
        if (a != b) {
            for (int i = MAX_LVL; i >= 0; --i) {
                if (par[a][i] != par[b][i]) {
                    a = par[a][i];
                    b = par[b][i];
                }
                lca = par[a][i];
            }
        }
        cout << ans_x + ans_y - dist[lca] * 2 << "\n";
    }

    return 0;
}

'BOJ' 카테고리의 다른 글

[BOJ 1693] 트리 색칠하기  (0) 2021.05.13
[BOJ 7812] 중앙트리  (0) 2021.05.12
[BOJ 3584] 가장 가까운 공통 조상  (0) 2021.05.08
[BOJ 1949] 우수 마을  (0) 2021.05.05
[BOJ 15681] 트리와 쿼리  (0) 2021.05.05
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
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
글 보관함