[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

题目分析:

首先可以想到只有集合点是两个点的LCA才能更优 那么枚举每两个点的LCA分别判断最优就好了

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m;
int head[500010],next[1000010],to[1000010];
int fa[500010][25],deep[5000010];
int tot;
void add(int x,int y)
{
    next[++tot]=head[x];
    to[tot]=y;
    head[x]=tot;
}
void dfs(int x,int temp)
{
    deep[x]=deep[temp]+1;
    fa[x][0]=temp;
    for(int i=1;fa[x][i-1];i++)
        fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i=head[x];i;i=next[i])
        if(to[i]!=temp) dfs(to[i],x);
}
int lca(int x,int y)
{
    if(deep[x]<deep[y]) swap(x,y);
    int temp=20;
    while(temp>=0)
    {
        if(deep[fa[x][temp]]>=deep[y]) x=fa[x][temp];
        temp--;
    }
    temp=20;
    if(x==y) return x;
    while(temp>=0)
    {
        if(fa[x][temp]!=fa[y][temp]) 
            x=fa[x][temp],y=fa[y][temp];
        temp--;
    }
    return fa[x][0];
}
void check()
{
    int x,y,z;
    scanf("%d%d%d",&x,&y,&z);
    int tmp1=lca(x,y),tmp2=lca(x,z),tmp3=lca(y,z);
    int nmp1=lca(tmp1,z),nmp2=lca(tmp2,y),nmp3=lca(tmp3,x);
    int tmp,ans=0x7f7f7f7f,num;
    tmp=deep[x]+deep[y]-deep[tmp1]+deep[z]-(deep[nmp1]<<1);
    if(tmp<ans) num=tmp1,ans=tmp;
    tmp=deep[x]+deep[z]-deep[tmp2]+deep[y]-(deep[nmp2]<<1);
    if(tmp<ans) num=tmp2,ans=tmp;
    tmp=deep[y]+deep[z]-deep[tmp3]+deep[x]-(deep[nmp3]<<1);
    if(tmp<ans) num=tmp3,ans=tmp;
    printf("%d %d\n",num,ans);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++)
    {
        int x,y;    
        scanf("%d%d",&x,&y);
        add(x,y),add(y,x);
    }
    dfs(1,0);
    for(int i=1;i<=m;i++)
        check();
}

发表评论

邮箱地址不会被公开。 必填项已用*标注