LCA(倍增)

来源:互联网 发布:淘宝管控记录中的商品 编辑:程序博客网 时间:2024/05/19 18:11

LCA的倍增算法,算是一种比较好些并且使用率很高的算法了

//这里写代码片#include<cstdio>#include<cstring>#include<iostream>#include<cmath>using namespace std;const int N=500005;struct node{    int x,y,nxt;};node way[N<<1];int pre[N][20],deep[N],n,m,root,st[N],tot=0,lg;void add(int u,int w){    tot++;    way[tot].x=u;way[tot].y=w;way[tot].nxt=st[u];st[u]=tot;    tot++;    way[tot].x=w;way[tot].y=u;way[tot].nxt=st[w];st[w]=tot;}void dfs(int now,int fa,int dep){    deep[now]=dep;    pre[now][0]=fa;    for (int i=st[now];i;i=way[i].nxt)        if (way[i].y!=fa)           dfs(way[i].y,now,dep+1);}void cl(){    lg=log(n)/log(2)+1;    for (int i=1;i<=lg;i++)        for (int j=1;j<=n;j++)            pre[j][i]=pre[pre[j][i-1]][i-1];}int ask(int u,int w){    if (deep[u]<deep[w]) swap(u,w);    int d=deep[u]-deep[w];    if (d)        for (int i=0;i<=lg&&d;i++,d>>=1)            if (d&1)                u=pre[u][i];    if (u==w) return u;    for (int i=lg;i>=0;i--)        if (pre[u][i]!=pre[w][i])        {            u=pre[u][i];            w=pre[w][i];        }    return pre[u][0];}int main(){    scanf("%d%d%d",&n,&m,&root);    for (int i=1;i<n;i++)    {        int u,w;        scanf("%d%d",&u,&w);        add(u,w);    }    dfs(root,0,1);    cl();    for (int i=1;i<=m;i++)    {        int u,w;        scanf("%d%d",&u,&w);        printf("%d\n",ask(u,w));    }    return 0;}