zoukankan      html  css  js  c++  java
  • CF832D Misha, Grisha and Underground |LCA

    有一棵n个节点的树,一共q 次询问

    每次询问给定3个点,求两条起点终点在这三个点上且不完全重合的路径的最多公共节点数


    简单LCA求距离,令a为汇合点,那么答案就是(dis(a,b) + dis(a,c) - dis(b,c)) / 2 + 1,dis用lca求出,枚举a就好。

    当然也可以一一讨论abc的位置关系,不过容易出错。

    #include<queue>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=2e5+10;
    #define int long long
    int Next[N*2],head[N],go[N*2],tot;
    inline void add(int u,int v){
    	Next[++tot]=head[u];head[u]=tot;go[tot]=v;
    	Next[++tot]=head[v];head[v]=tot;go[tot]=u;
    }
    int n,q;
    int d[N],f[N][21];
    inline void pre(int u,int fa){
    	d[u]=d[fa]+1;f[u][0]=fa;
    	for(int i=1;i<=20;i++)f[u][i]=f[f[u][i-1]][i-1];
    	for(int i=head[u];i;i=Next[i]){
    		int v=go[i];
    		if(v==fa)continue;
    		pre(v,u);
    	}
    }
    inline int LCA(int x,int y){
    	if(d[x]<d[y])swap(x,y);
    	for(int i=20;i>=0;i--)if(d[f[x][i]]>=d[y])x=f[x][i];
    	if(x==y)return x;
    	for(int i=20;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    inline int dis(int a,int b){
    	int c=LCA(a,b);
    	return d[a]-d[c]+d[b]-d[c];
    }
    inline int ask(int a,int b,int c){
    	return 1+(dis(a,b)+dis(a,c)-dis(b,c))>>1;
    }
    signed main(){
    	cin>>n>>q;
    	for(int i=2,x;i<=n;i++)
    	scanf("%lld",&x),add(x,i);
    	pre(1,0);
    	int a,b,c;
    	while(q--){
    		scanf("%lld%lld%lld",&a,&b,&c);
    		int ans=0;
    		ans=max(ans,ask(a,b,c));
    		ans=max(ans,ask(b,a,c));
    		ans=max(ans,ask(c,b,a));
    		printf("%lld
    ",ans);
    	}
    }
    
  • 相关阅读:
    iOS网络编程--NSConnection的同步连接与异步连接
    NSThread基础使用
    多线程基础
    《软件工程》总结
    作业4(结对编程项目--四则运算)
    PSP记录个人项目耗时情况
    作业3
    作业二 流行的源程序版本管理软件和项目管理软件各自的优点缺点
    作业2
    作业
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/11765803.html
Copyright © 2011-2022 走看看