【最近公共祖先】树倍增算法

来源:互联网 发布:mac用户头像 编辑:程序博客网 时间:2024/05/17 09:47

想想当年单纯的以为树剖求最近公共祖先就行啦,学什么LCA,结果NOIP2016原地爆炸……
所以说来填个坑
用类似st表的方法,来记录祖先。
从上至下,找公共祖先,最后一个肯定是最近的了。

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;struct node{    int x,y,next;}a[210000];int len,last[110000];void ins(int x,int y){    a[++len].x=x;a[len].y=y;    a[len].next=last[x];last[x]=len;}//f[i][j]表示j的第2^i的祖先int Bin[30],dep[110000],f[25][110000];void dfs(int x,int fa){    f[0][x]=fa;    for(int i=1;Bin[i]<=dep[x];i++)f[i][x]=f[i-1][f[i-1][x]];    for(int k=last[x];k;k=a[k].next)    {        int y=a[k].y;        if(y!=fa)        {            dep[y]=dep[x]+1;            dfs(y,x);        }    }}int LCA(int x,int y){    if(dep[x]<dep[y])swap(x,y);    for(int i=20;i>=0;i--)        if(dep[x]-dep[y]>=Bin[i])x=f[i][x];    if(x==y)return x;    for(int i=20;i>=0;i--)        if(dep[x]>=Bin[i]&&f[i][x]!=f[i][y]){x=f[i][x];y=f[i][y];}    return f[0][x];}int main(){    Bin[0]=1;for(int i=1;i<=25;i++)Bin[i]=Bin[i-1]*2;    int n,m,x,y;    scanf("%d%d",&n,&m);    len=0;memset(last,0,sizeof(last));    for(int i=1;i<n;i++)    {        scanf("%d%d",&x,&y);        ins(x,y);ins(y,x);    }    dep[1]=1;dfs(1,0);    while(m--)    {        scanf("%d%d",&x,&y);        printf("%d\n",LCA(x,y));    }    return 0;}
原创粉丝点击