zoukankan      html  css  js  c++  java
  • 题解 [BZOJ1832][AHOI2008] 聚会

    题面

    解析

    首先对于其中的两个点(x,y)最近的点显然就是他们的(lca)(我们把它设为(p1)),

    然后考虑第三个点(z)(p1)(lca,p2).

    有以下几种情况:

    1. (dep[p1]>=dep[p2])(也就是(p2)(p1)上面或(p1=p2)),这时候答案显然就是(p1).

    2. (dep[p1]<dep[p2]),这时候我们求出(p3=lca(x,z),p4=lca(y,z))

      1. (dep[p3]>dep[p4]),这时候(p3)显然更优(画下图或者(yy)一下就能理解)
      2. (dep[p4]>dep[p3]),同理,就是反过来...
      3. (p3=p4),随便选一个...

    最后用深度算距离就行啦.

    code(似乎有点卡常):

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define fre(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
    using namespace std;
    
    inline int read(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    	return f*sum;
    }
    
    const int N=500005;
    struct edge{int to,next;}e[N<<1];
    int n,m;
    int head[N],cnt;
    int fa[N][20],dep[N];
    
    inline void add(int x,int y){
    	e[++cnt]=(edge){head[x],y};head[x]=cnt;
    }
    
    inline void dfs(int x,int f){
    	fa[x][0]=f;dep[x]=dep[f]+1;
    	for(int i=1;i<20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
    	for(int i=head[x];i;i=e[i].to){
    		int k=e[i].next;if(k==f) continue;
    		dfs(k,x);
    	}
    }
    
    inline int lca(int x,int y){
    	if(dep[x]<dep[y]) swap(x,y);
    	for(int i=19;i>=0;i--){
    		if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
    	}
    	if(x==y) return x;
    	for(int i=19;i>=0;i--){
    		if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    	}
    	return fa[x][0];
    }
    
    int main(){
    	n=read();m=read();
    	for(int i=1;i<n;i++){int x=read(),y=read();add(x,y);add(y,x);}
    	dfs(1,0);
    	for(int i=1;i<=m;i++){
    		int x=read(),y=read(),z=read();
    		int p1=lca(x,y),p2=lca(p1,z);
    		if(dep[p2]<dep[p1]){
    			printf("%d %d
    ",p1,dep[x]-dep[p1]+dep[y]-dep[p1]+dep[p1]-dep[p2]+dep[z]-dep[p2]);
    		}
    		else{
    			int p3=lca(x,z),p4=lca(y,z);
    			if(dep[p3]>=dep[p4])
    				printf("%d %d
    ",p3,dep[x]-dep[p3]+dep[z]-dep[p3]+dep[y]-dep[p1]+dep[p3]-dep[p1]);
    			else
    				printf("%d %d
    ",p4,dep[y]-dep[p4]+dep[z]-dep[p4]+dep[x]-dep[p1]+dep[p4]-dep[p1]);
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Linux 常用命令--来自B站Up主codesheep
    如何区别调用python2和python3
    fastp 使用
    使用bash shell删除目录中的特定文件的3种方法
    python 正则表达式 finditer
    vcf format
    vcf文件(call variants得来的)怎么看变异是纯合还是杂合
    js Object.preventExtensions()
    js 对象的属性特征
    shell基础 以及 sed、awk
  • 原文地址:https://www.cnblogs.com/zsq259/p/11415347.html
Copyright © 2011-2022 走看看