模板 树上求LCA 倍增和树链剖分

//233

模板 LCA
void dfs(int x,int f){
    for(int i=0;i<E[x].size();i++){
        int v = E[x][i];
        if(v==f)continue;
        deep[v]=deep[x]+1;
        lca[v][0]=x;
        for(int j=1;j<maxm;j++){
            int fa = lca[v][j-1];
            if(fa==0)continue;
            lca[v][j]=lca[fa][j-1];
        }
        dfs(v,x);
    }
}
int up(int x,int d)
{
    for(int i=maxm-1;i>=0;i--)
    {
        if(d<(1<<i))continue;
        x=lca[x][i];
        d-=(1<<i);
    }
    return x;
}
int Lca(int x,int y)
{
    if(deep[x]>deep[y])swap(x,y);
    y=up(y,deep[y]-deep[x]);
    if(x==y)return x;
    for(int i=maxm-1;i>=0;i--)
    {
        if(lca[x][i]!=lca[y][i])
            x=lca[x][i],y=lca[y][i];
    }
    return lca[x][0];
}

//树链剖分
#include <cstdio>
#include <cstdlib>
#define maxm 200010
struct edge{int to,len,next;}E[maxm];
int cnt,last[maxm],fa[maxm],top[maxm],deep[maxm],siz[maxm],son[maxm],val[maxm];
void addedge(int a,int b,int len=0)
{
    E[++cnt]=(edge){b,len,last[a]},last[a]=cnt;
}
void dfs1(int x)
{
    deep[x]=deep[fa[x]]+1;siz[x]=1;
    for(int i=last[x];i;i=E[i].next)
    {
        int to=E[i].to;
        if(fa[x]!=to&&!fa[to]){
            val[to]=E[i].len;
            fa[to]=x;
            dfs1(to);
            siz[x]+=siz[to];
            if(siz[son[x]]<siz[to])son[x]=to;
        }
    }
}
void dfs2(int x)
{
    if(x==son[fa[x]])top[x]=top[fa[x]];
    else top[x]=x;
    for(int i=last[x];i;i=E[i].next)if(fa[E[i].to]==x)dfs2(E[i].to);
}
void init(int root){dfs1(root),dfs2(root);}
int query(int x,int y)
{
    for(;top[x]!=top[y];deep[top[x]]>deep[top[y]]?x=fa[top[x]]:y=fa[top[y]]);
    return deep[x]<deep[y]?x:y;
}
int n,m,x,y,v;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);addedge(x,y,v);addedge(y,x,v);
    }
    init(1);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        printf("%d\n",query(x,y));
    }
    return 0 ;
}
posted @ 2016-08-10 09:41  qscqesze  阅读(423)  评论(0编辑  收藏  举报