题解:

显然集合点为lca(x,y).lca(y,z),lca(z,x)中的一个

然后暴力计算即可

lca倍增即可

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5,K=20;
int x,y,num,n,m,zz[N],f[K][N],z,fi[N],deep[N],l,out[N],in[N],ne[N];
void dfs(int x,int y)
{
    in[x]=++l;
    f[0][x]=y;
    for (int i=fi[x];i;i=ne[i])
     if (y!=zz[i])
      {
          deep[zz[i]]=deep[x]+1;
          dfs(zz[i],x);
      }
    out[x]=++l;  
}
void jb(int x,int y)
{
    ne[++num]=fi[x];
    fi[x]=num;
    zz[num]=y;
}
int pd(int x,int y)
{
    return in[x]<=in[y]&&out[x]>=out[y];
}
int lca(int x,int y)
{
    if (x==y)return x;
    if (deep[x]<deep[y])swap(x,y);
    for (int i=19;i>=0;i--)
     if (f[i][x]!=0&&!pd(f[i][x],y))x=f[i][x];
    return f[0][x]; 
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<n;i++)
     {
         scanf("%d%d",&x,&y);
         jb(x,y);jb(y,x);
     }
    deep[1]=1; 
    dfs(1,0);
    for (int i=1;i<K;i++)
     for (int j=1;j<=n;j++)f[i][j]=f[i-1][f[i-1][j]];
    while (m--)
     {
         scanf("%d%d%d",&x,&y,&z);
         int x1=lca(x,y),x2=lca(y,z),x3=lca(x,z);
         int s1=deep[x]+deep[y]-deep[x1];
         int s2=deep[y]+deep[z]-deep[x2];
         int s3=deep[x]+deep[z]-deep[x3];
         int y1=lca(x1,z),y2=lca(x,x2),y3=lca(x3,y);
        s1+=deep[z]-2*deep[y1],s2+=deep[x]-2*deep[y2],s3+=deep[y]-2*deep[y3];
        int ans=x1,num=s1;
        if (s2<num)
         {
             num=s2;
             ans=x2;
         }
        if (s3<num)
         {
             num=s3; 
             ans=x3;
         } 
        printf("%d %d\n",ans,num);
     }  
}

 

posted on 2018-03-13 17:46  宣毅鸣  阅读(116)  评论(0编辑  收藏  举报