树论

LCA:树剖、倍增、Tarjan

  • 树剖 - O(logn)(n<=10^6)

  • https://www.cnblogs.com/cangT-Tlan/p/8846408.html

  • 把一棵树分成几条链,用数据结构去维护每一条链

  • #include<bits/stdc++.h>
    #define ll long long
    #define rll register ll
    #define M 0x3f3f3f
    #define For(i,l,r) for(int i=l;i<=r;i++)
    using namespace std; 
    ll n,m,s,head[M],a[M],x,y,z,tot,k,t;
    ll fa[M],d[M],top[M],size[M],id[M],ril[M];
    struct node1{
        ll to,nxt;
    }e[M<<1];
    struct node2{
        ll l,r,sum,flag;
    }tree[M<<1];
    
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    
    inline void add(ll x,ll y){
        e[++tot].to=y;
        e[tot].nxt=head[x];
        head[x]=tot;
    }
    
    inline void dfs1(ll u){//第一遍dfs遍历树,预处理d深度,size此点子节点个数,fa其父节点
        d[u]=d[fa[u]]+1;
        size[u]=1;
        for(rll i=head[u];i;i=e[i].nxt){
            if(e[i].to!=fa[u]){
                fa[e[i].to]=u;
                dfs1(e[i].to);
                size[u]+=size[e[i].to];
            }
        }
    }
    
    inline void dfs2(ll u){//按照子节点个数多少划分轻重边,保证一个点只在一条链中。一般只用重边,轻边用不到。
        ll t=0;//top即为此点所在重边的顶点 
        if(!top[u]) top[u]=u;
        for(rll i=head[u];i;i=e[i].nxt){
            if(e[i].to!=fa[u]&&size[e[i].to]>t) t=e[i].to;
        }
        if(t){
            top[t]=top[u];
            dfs2(t);
        }
        for(rll i=head[u];i;i=e[i].nxt){
            if(e[i].to!=fa[u]&&e[i].to!=t) dfs2(e[i].to); 
        }
    }
    
    inline ll lca(ll x,ll y){//当两个点位于同一条重链上即结束操作。否则深度深的点跳到所在重链的上一个点,结束操作时深度浅的点的位置即为所求lca
        while(top[x]!=top[y]){
            if(d[top[x]]<d[top[y]]) swap(x,y);
            x=fa[top[x]];
        }
        if(d[x]>d[y]) swap(x,y);
        return x;
    }
    
    int main(){
        n=read(),m=read(),s=read();
        For(i,1,n-1) {x=read(),y=read(),add(x,y),add(y,x);}
        dfs1(s),dfs2(s);
        For(i,1,m){x=read(),y=read(),printf("%lld\n",lca(x,y));}
        return 0;
    }
  • 题目:

  1. 仓鼠找sugar

猜你喜欢

转载自www.cnblogs.com/wi1d3on/p/11330532.html