倍增感受,以及lca倍增模板

感觉倍增就是用来加速状态转移的,如果某一种状态转移具有相同的变化状态,并且满足结合律,那么可以用倍增来加速状态转移。

一个经典的应用就是lca,或者说是求某条路径的第k个点。。

对于lca来说很明显他的每次往上走去寻找祖先,每一次的状态的变化规则是相同的,所以我们可以用倍增来优化,把每个点的第2^0..2^1..2^2距离的点处理出来,然后每一次

查询lca的两个点,我们先把高度统一到相同高度,然后再找到最大层数不满足两者祖先相同的高度

下面是模板:

const int M = 30;//n的log
int dep[MX], fa[MX][M], n;
 void DFS(int u, int _dep, int _fa) 
 { 
     dep[u] = _dep; 
     fa[u][0] = _fa; 
     for(int i = Head[u]; ~i; i = E[i].nxt) { 
        int v = E[i].v; 
     if(v == u || v == _fa) continue;
      DFS(v, _dep + 1, u); } 
} 
/*记得构图后要初始化一遍*/ 
void presolve()
 { DFS(1, 0, 1); 
 for(int i = 1; i < M; i++) {
        for(int j = 1; j <= n; j++) { 
            fa[j][i] = fa[fa[j][i - 1]][i - 1]; } 
 }
} /*倍增法要理解对2的次方的枚举顺序 如果是要走固定步数,那么顺序枚举与i位与为1就行 如果是要求一个临界位置,那么要从大到小枚举 */ 
int LCA(int u, int v) {
     while(dep[u] != dep[v]) {
            if(dep[u] < dep[v]) swap(u, v); 
     int d = dep[u] - dep[v]; 
     for(int i = 0; i < M; i++) { 
            if(d >> i & 1) u = fa[u][i];
     }
    } 
    if(u == v) return u; 
    for(int i = M - 1; i >= 0; i--) 
    { 
        if(fa[u][i] != fa[v][i]) {
             u = fa[u][i]; v = fa[v][i]; } 
    }
     return fa[u][0]; 
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值