• 【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;
    }
  • 相关阅读:
    Net
    GUI
    第三方模块
    步入大四的第一天 2020/9/3
    期末复习计划及每日更新 8/10-9/2
    成都,come back 2020/8/10
    回家第三天 2020/7/31
    连续两天的好太阳的一天 2020/7/27
    规划规划,接下来的一个月该如何安排 7/25
    紧紧张张又兴兴奋奋的一天 2020/7/24
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6639205.html
Copyright © 2020-2023  润新知