[AHOI2008]紧急集合 / 聚会

#include <cstdio>
#include <cmath>
#include <vector>
#define MAXN 500005
#define GetDis(x, y) (Dep[x] + Dep[y] - (Dep[LCA(x, y)] << 1))
#define gc (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 18, stdin), p1 == p2) ? EOF : *p1 ++ )

char buf[1 << 18], *p1, *p2;

inline int read() {
    char ch;
    int x(0);
    while ((ch = gc) < 48);
    while (ch >= 48) x = x * 10 + ch - 48, ch = gc;
    return x;
}

int fa[MAXN][20], Dep[MAXN], tot, n;
std::vector<int> sons[MAXN];

inline void dfs(int u) {
    int MAX(ceil(log2(Dep[u] = Dep[fa[u][0]] + 1)));
    for (int i(1); i <= MAX; ++ i)
    fa[u][i] = fa[fa[u][i - 1]][i - 1];
    for (auto i : sons[u]) if (i != fa[u][0]) fa[i][0] = u, dfs(i);
}

inline int LCA(int x, int y) {
    if (Dep[x] < Dep[y]) {int t(x); x = y, y = t;}
    int MAX(ceil(log2(n)));
    for (int i(0); i <= MAX; ++ i) if (Dep[x] - Dep[y] & 1 << i) x = fa[x][i];
    if (x == y) return x;
    for (int i(ceil(log2(Dep[x]))); i >= 0; -- i)
    if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
    return fa[x][0];
}

inline void cmp(int x, int y, int z) {
    int t1(LCA(x, y)), t2(LCA(x, z)), t3(LCA(y, z));
    if (t1 == t2 && t2 != t3)
        printf("%d %d\n", t3, Dep[y] + Dep[z] - (Dep[t3] << 1) + GetDis(x, t3));
    else if (t1 == t3 && t2 != t3)
        printf("%d %d\n", t2, Dep[x] + Dep[z] - (Dep[t2] << 1) + GetDis(y, t2));
    else printf("%d %d\n", t1, Dep[x] + Dep[y] - (Dep[t1] << 1) + GetDis(z, t1));
}

int main() {
    n = read();
    int m(read());
    for (int i(1); i < n; ++ i) {
        int x(read()), y(read());
        sons[x].push_back(y), sons[y].push_back(x);
    }
    dfs(1);
    while (m --) cmp(read(), read(), read());
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值