Codeforces 832D. Misha, Grisha and Underground【LCA】

题意:已知一棵树节点数n,n-1 条边组成。Q次询问,现在从中选取3个点a,b,c。 以一个点为顶点,另外两个点为起始点走最短路。要求得3种组合中,公共点数量最多的情况。


思路:枚举3种情况。

节点A,B之间最短路距离是:dis(A,B)=dep[A]-dep[LCA(A,B)]+dep[B]-dep[LCA(A,B)];

两节点A,B到节点C的    公共点个数=  (  dis(A,C)+dis(B,C)-dis(A,B)  )/2  + 1

接下来主要是模板一套就好了


数据分析:2 ≤ n ≤ 1051 ≤ q ≤ 105


复杂度分析:O(nlogn + q * logn)


CODE:(详见 算法学习之   LCA模板)传送门

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn=1e5+50;
const int maxlog=20;
int n,q,root=1;
int par[maxlog][maxn];
int dep[maxn];
vector <int> G[maxn];

void dfs(int v,int p,int d)
{
    par[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);
    return ;
}

void init()
{
    dfs(root,-1,0);
    for(int k=0;k<=maxlog-2;k++)
        for(int v=1;v<=n;v++)
            par[k+1][v]= par[k][v]<0 ? -1:par[k][par[k][v]];

    return ;
}

int lca(int u,int v)
{
    if(dep[u]>dep[v])   swap(u,v);
    for(int k=0;k<maxlog;k++)
        if((dep[v]-dep[u])>>k & 1)
            v=par[k][v];
    if(u==v)    return u;
    for(int k=maxlog-1;k>=0;k--)
        if(par[k][u]!=par[k][v])    u=par[k][u],v=par[k][v];
    return par[0][u];
}

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

int cul(int t, int s ,int f){return (  dis(s,f)+dis(t,f)-dis(s,t)  )/2;}

int main(void)
{
    cin >> n >> q;
    for(int i=2;i<=n;i++)
    {
        int t;
        scanf("%d",&t);
        G[i].push_back(t);
        G[t].push_back(i);
    }
    init();
    while(q--)
    {

        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        printf("%d\n",max(  cul(a,b,c),max(cul(a,c,b) , cul(b,c,a)) )+1  );
    }
    return 0;
}


全部评论

相关推荐

07-18 15:02
门头沟学院 Java
刚打开网申页面就不想填了,还是不要为难自己了
poppinzhan...:多益老行业毒瘤了,碰到徐波这种恶心的烂人,去了也是受罪。
点赞 评论 收藏
分享
07-15 00:33
江苏大学 Java
代码飞升:哈哈哈哈评论区三个打广告的
简历中的项目经历要怎么写
点赞 评论 收藏
分享
机械打工仔:我来告诉你原因,是因为sobb有在线简历,有些HR为了快会直接先看在线简历,初步感觉不合适就不会找你要详细的了
投了多少份简历才上岸
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务