码迷,mamicode.com
首页 > 其他好文 > 详细

LCA 倍增||树链剖分

时间:2016-12-14 01:49:51      阅读:232      评论:0      收藏:0      [点我收藏+]

标签:turn   include   str   bin   algo   struct   深度   wap   name   

方法1:倍增

1498ms

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=5e5+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
    return x*f;
}
int n,q,root,a,b;
struct edge{
    int v,ne;
}e[N<<1];
int cnt=0,h[N];
inline void ins(int u,int v){
    cnt++;
    e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
    cnt++;
    e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
int fa[N][21],deep[N],vis[N];
void dfs(int u){
    vis[u]=1;
    for(int j=1;(1<<j)<=deep[u];j++)
        fa[u][j]=fa[fa[u][j-1]][j-1];
    for(int i=h[u];i;i=e[i].ne){
        int v=e[i].v;
        if(vis[v]) continue;
        deep[v]=deep[u]+1;
        fa[v][0]=u;
        dfs(v);
    }
}
int lca(int x,int y){
    if(deep[x]<deep[y]) swap(x,y);
    int bin=deep[x]-deep[y];
    for(int i=0;i<=16;i++)
        if((1<<i)&bin) x=fa[x][i];//,printf("x %d\n",i);
    
    for(int i=16;i>=0;i--)
        if(fa[x][i]!=fa[y][i]){
            x=fa[x][i];
            y=fa[y][i];
        }
    if(x==y) return x;
    else return fa[x][0];
}
int main(int argc, const char * argv[]) {
    n=read();q=read();root=read();
    for(int i=1;i<=n-1;i++) a=read(),b=read(),ins(a,b);
    dfs(root);
    for(int i=1;i<=q;i++){
        a=read();b=read();
        printf("%d\n",lca(a,b));
    }
    return 0;
}

方法2:树链剖分

1314ms

让链首深度大的走到重链的父节点直到在一条重链上,返回深度小的节点

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=5e5+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
    return x*f;
}
int n,q,root,a,b;
struct edge{
    int v,ne;
}e[N<<1];
int cnt=0,h[N];
inline void ins(int u,int v){
    cnt++;
    e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
    cnt++;
    e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
int fa[N],deep[N],mx[N],size[N];
void dfs(int u){
    size[u]++;
    for(int i=h[u];i;i=e[i].ne){
        int v=e[i].v;
        if(v==fa[u]) continue;
        fa[v]=u;deep[v]=deep[u]+1;
        dfs(v);
        size[u]+=size[v];
        if(size[v]>size[mx[u]]) mx[u]=v;
    }
}
int tid[N],top[N],tot;
void dfs(int u,int anc){
    if(!u) return;
    tid[u]=++tot;top[u]=anc;
    dfs(mx[u],anc);
    for(int i=h[u];i;i=e[i].ne){
        int v=e[i].v;
        if(v!=fa[u]&&v!=mx[u]) dfs(v,v);
    }
}
int lca(int x,int y){
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    return x;
}
int main(int argc, const char * argv[]) {
    n=read();q=read();root=read();
    for(int i=1;i<=n-1;i++) a=read(),b=read(),ins(a,b);
    dfs(root);
    dfs(root,root);
    for(int i=1;i<=q;i++){
        a=read();b=read();
        printf("%d\n",lca(a,b));
    }
    return 0;
}

 

LCA 倍增||树链剖分

标签:turn   include   str   bin   algo   struct   深度   wap   name   

原文地址:http://www.cnblogs.com/candy99/p/6172334.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!