• 【BZOJ1787】[Ahoi2008]Meet 紧急集合 LCA


    【BZOJ1787】[Ahoi2008]Meet 紧急集合

    Description

    Input

    Output

    Sample Input

    6 4
    1 2
    2 3
    2 4
    4 5
    5 6
    4 5 6
    6 3 1
    2 4 4
    6 6 6

    Sample Output

    5 2
    2 5
    4 1
    6 0

    HINT

    题解:自己画画图就能看出来,对于询问(a,b,c),我们两两求出LCA,然后一定是选择深度最大的LCA作为集合点。就没有然后了

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn=500010;
    int n,m,cnt;
    int to[maxn<<1],next[maxn<<1],head[maxn],fa[maxn][22],dep[maxn];
    void dfs(int x)
    {
    	for(int i=head[x];i!=-1;i=next[i])
    	{
    		if(to[i]==fa[x][0])	continue;
    		fa[to[i]][0]=x,dep[to[i]]=dep[x]+1,dfs(to[i]);
    	}
    }
    void add(int a,int b)
    {
    	to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
    }
    int lca(int a,int b)
    {
    	if(dep[a]<dep[b])	swap(a,b);
    	int i;
    	for(i=19;i>=0;i--)	if(dep[fa[a][i]]>=dep[b])	a=fa[a][i];
    	if(a==b)	return a;
    	for(i=19;i>=0;i--)	if(fa[a][i]!=fa[b][i])	a=fa[a][i],b=fa[b][i];
    	return fa[a][0];
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	int i,j,a,b,c,x,y,z;
    	memset(head,-1,sizeof(head));
    	for(i=1;i<n;i++)
    	{
    		scanf("%d%d",&a,&b);
    		add(a,b),add(b,a);
    	}
    	dep[1]=1,dfs(1);
    	for(j=1;(1<<j)<=n;j++)	for(i=1;i<=n;i++)	fa[i][j]=fa[fa[i][j-1]][j-1];
    	for(i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&a,&b,&c);
    		x=lca(a,b),y=lca(b,c),z=lca(a,c);
    		if(dep[x]<dep[y])	swap(x,y);
    		if(dep[x]<dep[z])	swap(x,z);
    		if(dep[y]<dep[z])	swap(y,z);
    		printf("%d %d
    ",x,dep[a]+dep[b]+dep[c]-2*dep[z]-dep[x]);
    	}
    	return 0;
    }
  • 相关阅读:
    今日总结
    今日总结
    今日总结
    k8s controller
    深入k8s:Informer使用及其源码分析
    理解 K8S 的设计精髓之 List-Watch机制和Informer模块
    Unix domain socket 简介
    Linux网络编程——端口复用(多个套接字绑定同一个端口)
    DPVS Tutorial
    dpvs route RTF_KNI
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6639205.html
Copyright © 2020-2023  润新知