Tarjan找LCA,并查集,离线算法

#include <iostream>
#include <vector>
using namespace std;

const int N = 1e5 + 10;

int n, q;
vector<int> tree[N];
vector<pair<int, int>> queries[N]; // queries[i] 存储所有以 i 为端点的 (对端点, 查询编号)
int parent[N];  // 并查集
int lca_answer[N]; // 每个查询的 LCA 结果
bool visited[N];

int find(int x) {
    if (x != parent[x])
        parent[x] = find(parent[x]);
    return parent[x];
}

void tarjan(int u) {
    parent[u] = u;
    visited[u] = true;

    for (int v : tree[u]) {
        if (!visited[v]) {
            tarjan(v);
            parent[v] = u; // Union(v, u)
        }
    }

    for (auto& q : queries[u]) {
        int v = q.first, id = q.second;
        if (visited[v]) {
            lca_answer[id] = find(v);
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    // 读取节点数
    cin >> n;
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        tree[u].push_back(v);
        tree[v].push_back(u); // 无向树
    }

    // 读取查询数
    cin >> q;
    for (int i = 0; i < q; ++i) {
        int u, v;
        cin >> u >> v;
        queries[u].emplace_back(v, i);
        queries[v].emplace_back(u, i); // 双向查询
    }

    tarjan(1); // 假设根为 1

    // 输出所有查询的 LCA
    for (int i = 0; i < q; ++i) {
        cout << lca_answer[i] << '\n';
    }

    return 0;
}
posted @ 2025-08-13 15:42  majikko  阅读(10)  评论(0)    收藏  举报