您的位置:首页 > 其它

【BZOJ 1832】 [AHOI2008]聚会|倍增lca

2016-04-23 08:31 337 查看
100ac 留念

双倍经验题

两两求距离 相加除以二为距离

两两求lca depth最大为三个的lca

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN=500000+10;
int to[MAXN][20],depth[MAXN];
int tot,g[MAXN],nnext[MAXN*2],num[MAXN*2] ;
int team[MAXN],head,tail;
void add(int x,int y)
{
tot++;
nnext[tot]=g[x];
g[x]=tot;
num[tot]=y;
}
void bfs()
{
depth[1]=1;
team[++tail]=1;
while(head<tail)
{
int x=team[++head];
for(int i=1;i<=19;i++) to[x][i]=to[to[x][i-1]][i-1];
for(int i=g[x];i;i=nnext[i])
{
int tmp=num[i];
if(tmp==to[x][0]) continue;
depth[tmp]=depth[x]+1;
to[tmp][0]=x;
team[++tail]=tmp;
}
}
}
int lca(int x,int y)
{
if(depth[x]<depth[y])swap(x,y);
for(int i=19;i>=0;i--)
if(depth[to[x][i]]>=depth[y])
x=to[x][i];
if(x==y) return x;
for(int i=19;i>=0;i--)
if(to[x][i]!=to[y][i])
x=to[x][i],y=to[y][i];
return to[x][0];
}
int dis(int x,int y,int fa)
{
return abs(depth[x]-depth[fa])+abs(depth[y]-depth[fa]);
}
int main()
{
int n,m;
int x,y,z;
scanf("%d %d",&n,&m);
for(int i=1;i<n;i++) scanf("%d %d",&x,&y),add(x,y),add(y,x);
bfs();
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&x,&y,&z);
int zx=lca(x,z);
int zy=lca(z,y);
int xy=lca(x,y);
int ans=zx;
if(depth[ans]<depth[zy]) ans=zy;
if(depth[ans]<depth[xy]) ans=xy;
int tmp1=dis(x,y,xy);
int tmp2=(dis(x,z,zx)+dis(z,y,zy)-tmp1)/2;
printf("%d %d\n",ans,tmp1+tmp2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: