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

倍增——LCA

时间:2018-09-21 23:15:40      阅读:451      评论:0      收藏:0      [点我收藏+]

标签:using   输出   图片   audio   str   getc   div   algorithm   mes   

今天终于把倍增的LCA搞懂了!尽管周测都没写,尽管lca其实很简单,但这也是进度君的往前一点点的快乐。

倍增的lca其实关键就在于二进制的二进制的拆分(显然是两次的拆分,很奇妙,懂二进制的自然不觉得什么)。把最关键的地方在这里列举一下吧:

1.f[fa][i]=f[f[fa][i-1]][i-1];类似于状态转移,i表示2^i可以表示fa的2的i次方的祖先所以当前的fa的2^i的祖先就是它2-1次方的祖先的2-1次方的祖先

想要理解为什么是这样,1+1=2;2+2=4;4+4=8;8+8=16;故2^i-1+2^i-1=2^i;到这里就可以理解了吧。

2.for(int i=t;i>=0;i--) 这里的t是t=(int)(log(n)/log(2))+1;的出来的n是最大的数目也就是log数,if(depth[f[y][i]]>=depth[x]) y=f[y][i];这里的是指假如当前的深度和x的深度比,能调到和x一样深就跳,这个代码完成了将y跳到x,二进制的拆分就是如此神奇!!!。(dalao勿喷蒟蒻没见过二进制拆分)

3.for(int i=t;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];这里的也就是x,y虽然到了同样的深度但是呢,公共祖先还是没有出来所以可以进行同时向上爬(我要一步一步向上爬)因为二进制的拆分所以最后都会达到距离最近公共祖先最近的子节点处,所以最后输出x的父亲节点就是x,y的公共子节点了,二进制的拆分就是如此神奇!!!。(dalao勿喷蒟蒻没见过二进制拆分)

这就是lca的具体之处认真思考其实都很简单(无奈作业太多)多思考啊。

代码:

技术分享图片
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<map>
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
const int maxn=500001<<1;
const int maxx=500001;
int n,m,s,t;
int lin[maxn],nex[maxn],ver[maxn],len=0;
int depth[maxx],f[maxx][30];
void add(int x,int y)
{
    ver[++len]=y;
    nex[len]=lin[x];
    lin[x]=len;
}
void dfs(int fa,int fath)
{
    depth[fa]=depth[fath]+1;
    f[fa][0]=fath;
    for(int i=1;i<=t;i++)
        f[fa][i]=f[f[fa][i-1]][i-1];
    for(int i=lin[fa];i;i=nex[i])
        if(ver[i]!=fath)
            dfs(ver[i],fa);
}
int lca(int x,int y)
{
    if(depth[x]>depth[y])
        swap(x,y);
    for(int i=t;i>=0;i--)
        if(depth[f[y][i]]>=depth[x])
            y=f[y][i];
    if(x==y)
        return x;
    for(int i=t;i>=0;i--)
        if(f[x][i]!=f[y][i])
            x=f[x][i],y=f[y][i];
    return f[x][0];
}
int main()
{
    //freopen("1.in","r",stdin);
    n=read();m=read();s=read();
    t=(int)(log(n)/log(2))+1;
    for(int i=1;i<n;i++)
    {
        int x,y;
        x=read();y=read();
        add(x,y);add(y,x);
        
    }
    dfs(s,0);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        x=read();y=read();
        printf("%d\n",lca(x,y));
    }
    return 0;
}
View Code

高歌取醉欲自慰,起舞落日争光辉。

倍增——LCA

标签:using   输出   图片   audio   str   getc   div   algorithm   mes   

原文地址:https://www.cnblogs.com/chdy/p/9688552.html

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