首页 > 其他分享 >P4281 [AHOI2008] 紧急集合 / 聚会

P4281 [AHOI2008] 紧急集合 / 聚会

时间:2024-08-09 10:42:53浏览次数:7  
标签:idx fa int AHOI2008 紧急集合 dep P4281 lca dis

题意

给出 3 个点,选出一个点使得 3 个点到这个点的距离之和最小。

思路

  1. 三个点可以先取 2 个点的 lca,然后与第 3 个点再取 lca。
  2. 三个点的两两求 lca,至多只会有 2 个不同的结点。
  3. 三个点的距离 \(dis[x] + dis[y] + dis[z] - dis[lca(a, b)] - dis[lca(b, c)] - dis[lca(a, b)]\)。

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 500010;

struct edge {
    int to, next;
} e[N * 2];

int head[N], idx = 1;

void add(int u, int v) {
    idx++, e[idx].to = v, e[idx].next = head[u], head[u] = idx;
}

int fa[20][N], dep[N];
int n, q;

void dfs(int u, int f) {
    fa[0][u] = f;
    dep[u] = dep[f] + 1;
    for (int i = head[u]; i; i = e[i].next) {
        int to = e[i].to;
        if (to == f) continue;
        dfs(to, u);
    }
}

void initf() {
    for (int j = 1; j < 20; j++) {
        for (int i = 1; i <= n; i++) {
            fa[j][i] = fa[j - 1][fa[j - 1][i]];
        }
    }
}

int lca(int u, int v) {
    if (dep[u] < dep[v]) swap(u, v);

    for (int i = 19; i >= 0; i--) {
        if (dep[fa[i][u]] >= dep[v]) u = fa[i][u];
    }

    if (u == v) return u;

    for (int i = 19; i >= 0; i--) {
        if (fa[i][u]!= fa[i][v]) u = fa[i][u], v = fa[i][v];
    }
    return fa[0][u];
}

int dis(int u, int v) {
    return dep[u] + dep[v] - 2 * dep[lca(u, v)];
}

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

    cin >> n >> q;
    for (int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        add(u, v), add(v, u);
    }

    dfs(1, 0);
    initf();

    while (q--) {
        int u, v, w;
        cin >> u >> v >> w;
        int l1 = lca(u, v), l2 = lca(u, w), l3 = lca(v, w);
        int ans1, ans2;
        if (l1 == l2) ans1 = l3;
        else if (l1 == l3) ans1 = l2;
        else ans1 = l1;
        ans2 = dep[u] + dep[v] + dep[w] - dep[l1] - dep[l2] - dep[l3];
        cout << ans1 << ' ' << ans2 << '\n';
    }
    return 0;
}

标签:idx,fa,int,AHOI2008,紧急集合,dep,P4281,lca,dis
From: https://www.cnblogs.com/Yuan-Jiawei/p/18350322

相关文章

  • 紧急集合 / 聚会
    对于这道题目,我们考虑三个点的位置如果三个点共线,比如下面这个样子那么应该放在哪里呢?很显然应该放在中间这个点这里如果三个点不共线呢?这个时候我们以两个点为端点画线,再画出其他分支那么现在这个点应该放在哪里呢?应该放在中间“T”字形的交点那里于是我们就清楚了,结合上......
  • P4281 [AHOI2008]紧急集合 / 聚会
    此题来到LCA较高等级运用。这道题需要自己花一些树玩玩。找到一些性质:三个点的lca一定至少有两个是一样的;更多证明集合点就是不相同的点;同时还要会求树上距离这里......
  • Luogu P4793 [AHOI2008] 矩形藏宝地
    链接难度:\(\texttt{省选/NOI-}\)有\(n\)个矩形,左下角为\((x1,y1)\),右上角为\((x2,y2)\),问被其他的矩形包含的矩形有多少个。数据范围:\(1\len\le200000,x1<x2,y1<y......