1 条题解

  • 1
    @ 2023-1-29 11:04:10
    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 500000;
    const int MAXM = 500000;
    int n, q, root;          // 点数、询问个数、根节点
    vector<int> e[MAXN + 5]; // 存树
    int fa[MAXN + 5];
    int maxDep, dep[MAXN + 5];
    void dfs(int u, int father)
    {
        fa[u] = father;
        for (int i = 0; i < e[u].size(); i++)
        {
            int v = e[u][i];
            if (v == father)
                continue;
            dep[v] = dep[u] + 1;
            maxDep = max(maxDep, dep[v]);
            dfs(v, u);
        }
    }
    int lg2[MAXN + 5]; // 替代 log2(i)
    int dp[MAXN][35];  // i号点的 2^j 层祖先
    int lca(int u, int v)
    {
        if (dep[u] > dep[v])
            swap(u, v); // 让u的高度不低于v
        if (u == v)
            return u;
        // 把 v 提到与 u 同样高度
        for (int j = lg2[n]; j >= 0; j--)
            if ((1 << j) <= dep[v] - dep[u])
            {
                v = dp[v][j];
            }
        if (u == v)
            return u;
        // 找lca
        for (int j = lg2[n]; j >= 0; j--)
            if (dp[v][j] != dp[u][j])
            {
                v = dp[v][j],
                u = dp[u][j];
            }
        return dp[u][0];
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        //  输入
        cin >> n >> q;
        root = 1;
        for (int i = 1; i <= n - 1; i++)
        {
            int u, v;
            cin >> u >> v;
            e[u].push_back(v);
            e[v].push_back(u);
        }
        // 预处理:最大层数 maxDep、每个点的深度、记录父节点、log2[]、dp数组
        dep[root] = 1;
        maxDep = 1;
        dfs(root, 0);
        lg2[1] = 0;
        for (int i = 2; i <= n; i++)
            // i == 2^(log2(i-1)+1)
            if (i == (1 << (lg2[i - 1] + 1)))
                lg2[i] = lg2[i - 1] + 1;
            else
                lg2[i] = lg2[i - 1];
        for (int j = 0; j <= lg2[n]; j++)
        {
            for (int i = 1; i <= n; i++)
            {
                // 求解 dp[i][j]
                if (j == 0)
                    dp[i][j] = fa[i];
                else
                    dp[i][j] = dp[dp[i][j - 1]][j - 1];
            }
        }
        // q 次询问
        while (q--)
        {
            int x, y, z;
            cin >> x >> y >> z;
            int xy = lca(x, y);
            int xyz = lca(xy, z);
            int yz = lca(y, z);
            int xz = lca(x, z);
            int ans, ansi, nxt;
            // xy
            ans = dep[x] + dep[y] - 2 * dep[xy] +
                  dep[xy] + dep[z] - 2 * dep[xyz];
            ansi = xy;
            // yz
            nxt = dep[y] + dep[z] - 2 * dep[yz] +
                  dep[yz] + dep[x] - 2 * dep[xyz];
            if (nxt < ans)
                ans = nxt, ansi = yz;
            // xz
            nxt = dep[x] + dep[z] - 2 * dep[xz] +
                  dep[xz] + dep[y] - 2 * dep[xyz];
            if (nxt < ans)
                ans = nxt, ansi = xz;
            cout << ansi << " " << ans << "\n";
        }
        return 0;
    }
    
    
    • 1

    信息

    ID
    788
    时间
    2000ms
    内存
    512MiB
    难度
    4
    标签
    递交数
    30
    已通过
    18
    上传者