Codeforces Round #425 (Div. 2)D. Misha, Grisha and Underground(LCA)

来源:互联网 发布:c语言快速排序算法代码 编辑:程序博客网 时间:2024/05/17 03:34

题目链接

http://codeforces.com/contest/832/problem/D

题目大意

给你一棵树, 以及q次询问,每次询问给你a,b, c三个节点
你可以将这三个节点任意(一一对应)定为s, f, t节点,
然后进行以下操作
从s–>f跑最短路,并标记路上的点
从t–>f跑最短路,统计刚刚标记的点的个数
(每次询问过后标记的点会被清空)
问你每次询问统计出的标记的点个数的最大值

思路

树上最短路我们可以用LCA(两个节点最近的公共祖先)进行计算

我们用ab表示lca(a, b), ac = lca(a, c), bc = lca(b, c)
这样必定会有两个值相等, 如下图所示
这里写图片描述

那么最大值必然在三条路之间
a–>ab
b–>ab
c–>ab
至于路径的计算,lca计算过程中有一个deep数组,用于记录节点所在深度,那么a–>ab距离 = deep[a] - deep[ab], 以此类推

代码

#include<bits/stdc++.h>using namespace std;const int M = 1e5 + 5;vector<int>g[M];int root;int parent[20][M];int dep[M];int n, q;void dfs(int v, int p, int d){    parent[0][v] = p;    dep[v] = d;    for(int i=0; i<g[v].size(); ++i)    {        if(g[v][i]!=p) dfs(g[v][i], v, d+1);    }}void init(){    for(int k = 0; k < 20-1; ++ k)    {        for(int v = 1; v <= n; ++ v)        {            if(parent[k][v] < 0) parent[k+1][v] = -1;            else            {                parent[k+1][v] = parent[k][parent[k][v]];            }        }    }}int getlca(int u, int v){    if(dep[u] > dep[v]) swap(u, v);    int ans = 0;    for(int k = 0; k < 20; ++ k)    {        if((dep[v] - dep[u]) >> k & 1)        {            v = parent[k][v];        }    }    if(u != v)    {        for(int k = 20 - 1; k >= 0; -- k)        {            if(parent[k][u] != parent[k][v])            {                u = parent[k][u], v = parent[k][v];            }        }        u = parent[0][u];        return u;    }    return u;}int solve(int a, int b, int c, int ab, int ac){    int mx = 0;    mx = max(dep[a] - dep[ab] + 1, dep[b] - dep[ab] + 1);    mx = max(mx, dep[ab] - dep[ac] + dep[c] - dep[ac] + 1);    return mx;}int main(){    scanf("%d%d", &n, &q);    for(int i=1; i<n; ++i)    {        int tmp;        scanf("%d", &tmp);        g[i+1].push_back(tmp);        g[tmp].push_back(i+1);    }    dfs(1, -1, 1);    init();    for(int i=0; i<q; ++i)    {        int a, b, c, ans = 0;        scanf("%d%d%d", &a, &b, &c);        int ab = getlca(a, b);        int bc = getlca(b, c);        int ac = getlca(a, c);        int mx = max(dep[ab], max(dep[bc], dep[ac]));        if(dep[ab] == mx)        {            ans = solve(a, b, c, ab, ac);        }        else if(dep[ac] == mx)        {            ans = solve(a, c, b, ac, ab);        }        else if(dep[bc] == mx)        {            ans = solve(b, c, a, bc, ab);        }        printf("%d\n", ans);    }    return 0;}
阅读全文
0 0
原创粉丝点击