【bzoj1787】[Ahoi2008]Meet 紧急集合

时间:2023-03-09 07:40:01
【bzoj1787】[Ahoi2008]Meet 紧急集合

1787: [Ahoi2008]Meet 紧急集合

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 2466  Solved: 1117
[Submit][Status][Discuss]

Description

【bzoj1787】[Ahoi2008]Meet 紧急集合

Input

【bzoj1787】[Ahoi2008]Meet 紧急集合

Output

【bzoj1787】[Ahoi2008]Meet 紧急集合

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
【题解】
记住一个结论:三个点的最小距离点等于两两的lca中与其他两个lca不同的lca
然后就很水了。
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN 500010
struct node{int y,next;}e[MAXN*];
int n,m,len,ans,Link[MAXN],f[MAXN],deep[MAXN],anc[MAXN][];
inline int read()
{
int x=,f=; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-; ch=getchar();}
while(isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
}
void insert(int x,int y) {e[++len].next=Link[x];Link[x]=len;e[len].y=y;}
void dfs(int x,int fa)
{
anc[x][]=f[x];
for(int i=;i<=;i++) anc[x][i]=anc[anc[x][i-]][i-];
for(int i=Link[x];i;i=e[i].next)
if(e[i].y!=fa)
{
deep[e[i].y]=deep[x]+;
f[e[i].y]=x;
dfs(e[i].y,x);
}
}
int lca(int x,int y)
{
if(deep[x]<deep[y]) swap(x,y);
for(int i=;i>=;i--) if(deep[anc[x][i]]>=deep[y]) x=anc[x][i];
if(x==y) return x;
for(int i=;i>=;i--) if(anc[x][i]!=anc[y][i]) x=anc[x][i],y=anc[y][i];
return f[x];
}
int cal(int a,int b,int c) {if(a==b)return c;else if(a==c)return b;else return a;}
int dis(int x,int y) {int t=lca(x,y);return deep[x]+deep[y]-*deep[t];}
int main()
{
//freopen("cin.in","r",stdin);
//freopen("cout.out","w",stdout);
n=read(); m=read();
for(int i=;i<n;i++) {int x=read(),y=read(); insert(x,y); insert(y,x);}
deep[]=; dfs(,);
for(int i=;i<=m;i++)
{
int x=read(),y=read(),z=read();
int a=lca(x,y),b=lca(x,z),c=lca(y,z);
int p=cal(a,b,c);
ans=dis(x,p)+dis(y,p)+dis(z,p);
printf("%d %d\n",p,ans);
}
return ;
}