zoukankan      html  css  js  c++  java
  • CodeForces 832D. Misha, Grisha and Underground LCA

    传送门

    题意

    给你一棵树,然后给三个点 (a,b,c),求其中两个点到另一个点的最短路径的重合部分的最长值

    思路

    首先暴力一下是哪两个点到另一个点,取其中的最大值
    只要知道了三个点两两的公共祖先和三个点的公共祖先,剩下的就推一下重合部分的长度和位置的关系就行了
    当然从其他大神的题解中,我发现了更简单的解法:
    求出三个lca,并取深度最大的那个,就是我们要的三岔路口K,然后分别求出K到a,b,c三点的路径长度,取最大值+1就是答案。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=1e5+10;
    int n,q,st[MAXN][21],a[4],dep[MAXN];
    int head[MAXN],to[MAXN*2],nxt[MAXN*2],tot=1;
    
    void add(int u,int v){
    	to[++tot]=v;nxt[tot]=head[u];head[u]=tot;
    }
    
    void dfs(int u,int fa){
    	dep[u]=dep[fa]+1;st[u][0]=fa;
    	for(int i=head[u];i;i=nxt[i])
    		if(to[i]!=fa) dfs(to[i],u);
    }
    
    int lca(int x,int y){
    	if(dep[x]>dep[y]) swap(x,y);
    	for(int i=20;i>=0;i--) if(dep[st[y][i]]>=dep[x]) y=st[y][i];
    	if(x==y) return x;
    	for(int i=20;i>=0;i--) if(st[x][i]!=st[y][i]) x=st[x][i],y=st[y][i];
    	return st[x][0];
    }
    
    int calc(int a,int b,int c){
    	int ab=lca(a,b),bc=lca(b,c),ac=lca(a,c),abc=lca(ab,c);
    	if(a==b) return dep[a]+dep[c]-2*dep[ac]+1;
    	if(bc==ac) return abs(dep[abc]-dep[c])+1+abs(dep[abc]-dep[ab]);
    	else if(bc!=ab&&ac==ab) return abs(dep[bc]-dep[c])+1;
    	else if(ac!=ab&&bc==ab) return abs(dep[ac]-dep[c])+1;
    }
    
    int main(){
    	scanf("%d%d",&n,&q);
    	for(int i=2,x;i<=n;i++){
    		scanf("%d",&x);
    		add(i,x);add(x,i);
    	}
    	dfs(1,1);
    	for(int j=1;j<=20;j++)
    		for(int i=1;i<=n;i++)
    			st[i][j]=st[st[i][j-1]][j-1];
    	while(q--){
    		scanf("%d%d%d",&a[1],&a[2],&a[3]);
    		int ans=0;
    		sort(a+1,a+3+1);
    		do{
    			int temp=calc(a[1],a[2],a[3]);
    			ans=max(ans,temp);
    			
    		}while(next_permutation(a+1,a+3+1));
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    PAT-乙级-1034. 有理数四则运算(20)
    PAT-乙级-1033. 旧键盘打字(20)
    PAT-乙级-1032. 挖掘机技术哪家强(20)
    PAT-乙级-1031. 查验身份证(15)
    PAT-乙级-1030. *完美数列(25)
    PAT-乙级-1029. 旧键盘(20)
    PAT-乙级-1028. 人口普查(20)
    PAT-乙级-1027. 打印沙漏(20)
    PAT-乙级-1026. 程序运行时间(15)
    PAT-乙级-1025. 反转链表 (25)
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/12164558.html
Copyright © 2011-2022 走看看