【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
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
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; }