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

LCA及例题

时间:2019-09-21 23:24:24      阅读:113      评论:0      收藏:0      [点我收藏+]

标签:unsigned   ref   alt   detail   计算   如何   分析   dfs   return   

倍增法求LCA

(蒟蒻只会用倍增)
简单说就是先通过dfs预处理出每个节点i的深度deep[i]与其的第\(2^j\)个祖先f[i][j]。求f[i][j]的关键在于递推式f[i][j]=f[f[i][j-1]][j-1]。也即i的 \(2^j\) 祖先是 \(2^{j-1}\) 祖先的 \(2^{j-1}\) 祖先。
再求\(LCA\):首先将两节点的高度提升到同一水平,再同时提升两节点直至其父节点相同。当然,为了保证效率,两次提升都应该通过倍增法进行。
最终空间复杂度O(nlogn),预处理时间O(nlogn),单次查询时间O(logn)

const int N;//最多有N个节点
int n,deep[N],f[N][log_N];
vector<int> G[N];//无根树保存在这里

void dfs(int u,int ufa){ //预处理,ufa是u的父节点
    deep[u]=deep[ufa]+1;
    f[u][0]=ufa;
    for(int i=1;(1<<i)<=deep[u];i++)
        f[u][i]=f[f[u][i-1]][i-1];//求u的2^i祖先
    for(unsigned i=0;i<G[u].size();i++)
        if(G[u][i]!=ufa)
            dfs(G[u][i],u);//遍历u的所有儿子进行递归
int LCA(int u,int v){
    if(deep[u]<deep[v]) swap(u,v);//保证deep[u]>=deep[v]
    for(int i=log_n;i>=0;i--)//将u提到和v同一深度
        if(deep[u]>=deep[v]) u=f[u][i];
    if(u==v) return u;
    for(int i=log_n;i>=0;i--)//将u和v同时提升至其父节点相同
        if(f[u][i]!=f[v][i]){
            u=f[u][i];
            v=f[v][i];
        }
    return f[u][0];//此时u,v的父节点就是u,v的LCA
}

LCA的应用

P3379 LCA模板
P3884 二叉树问题
题意:给一棵二叉树,求深度、宽度(节点最多层的节点数)和两点u,v的距离(定义为u到LCA的路径长乘2加上v到LCA的路径长)。

点击查看题解
分析:利用LCA的副产品deep[i],可以很容易求出最深度和宽度。至于距离,u,v与LCA的路径长就是其深度的差值,按题意计算即可。

P4281 紧急集合
题意:给出一棵树以及三个点(多组数据),求与三个点的距离之和最小的点及距离之和。
点击查看题解
分析:画出分析图后发现这个点一定是每两点之间最深的LCA。如图,假设u=LCA(a,b)是三个LCA中最深的,那么v=LCA(a,c)=LCA(b,c)一定不会比u更好(多了uv之间的长度)。当然也可以找出与其他两个不同的LCA(因为三点间的LCA至少有两个相等,而除非u=v,u一定不与其他两个相同)
技术图片
至于距离,可以得出dis=deep[a]+deep[b]+deep[c]-deep[u]-2*deep[v]。又由u=LCA(a,b),v=LCA(a,c)=LCA(b,c),推出dis=deep[a]+deep[b]+deep[c]-deep[LCA(a,b)]-deep[LCA(b,c)]-deep[LCA(c,a)],这样也省去了分类讨论的麻烦。

P3398 仓鼠找sugar
题意:给出一颗树,以及四个数a,b,c,d(多组数据)。询问ab间最短路径与cd间最短路径是否相交。
点击查看题解
分析:显然最短路径就是两节点与LCA之间的路径。由于树的每一节点都只有一个父亲,那么两路径相交当且仅当一个路径的LCA在另一个路径上(否则交点就在两个路径上有两个父亲)。记L=LCA(u,v),那么如何判断一点p在路径u-L-v上呢?
这需要满足两个条件:1.deep[p]>=deep[L];2.LCA(p,u)=L或LCA(p,v)=L。当然,不必分两次判断,只需要先保证条件1成立(否则就交换)再判断条件2即可。

LCA及例题

标签:unsigned   ref   alt   detail   计算   如何   分析   dfs   return   

原文地址:https://www.cnblogs.com/yhyxy/p/11565258.html

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