• LCA在线处理 基于二分搜索


    记节点v到根点的深度为depth[v],那么当w是v和u的最近公共祖先时,可以想让v和u在同一个深度,即让深度高的走|depth[v]-depth[u]|然后一起走,

    直到遇见相同的祖先时就是最近公共祖先了。如果是计算一次的话还可以,但有很多询问时就不行了。

    那么可以利用父亲节点的信息来做了,可以通过parent2[v] = parent[parent[v]]得到v向上走两步的节点。在利用这个信息,

    又可以通过parent4[v] = parent2[parent2[v]]得到向上走4步得到的节点,这样搜索的复杂度是O(long(n))了,预处理parent[k][v]的复杂度是O(nlong(n))。

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <vector>
     4 #include <string.h>
     5 using namespace std;
     6 const int N = 1e4+10;
     7 vector<int> G[N];
     8 int vis[N], parent[30][N], depth[N], t, n;
     9 
    10 void dfs(int v, int p, int d){
    11     parent[0][v] = p;
    12     depth[v] = d;
    13     for(int i = 0; i < G[v].size(); i ++){
    14         if(G[v][i] != p) dfs(G[v][i],v,d+1);
    15     }
    16 }
    17 int lca(int u, int v){
    18     if(depth[u] > depth[v]) swap(u,v);
    19     for(int k = 0; k < 30; k ++){
    20         if((depth[v]-depth[u]) >> k&1){
    21             v = parent[k][v];
    22         }
    23     }
    24     if(v == u) return u;
    25     for(int k = 29; k >= 0; k--){
    26         if(parent[k][u] != parent[k][v]){
    27             u = parent[k][u];
    28             v = parent[k][v];
    29         }
    30     }
    31     return parent[0][u];
    32 }
    33 void init(){
    34     memset(parent,-1,sizeof(parent));
    35     for(int i = 1; i < N; i ++){
    36         parent[0][i] = i;
    37         G[i].clear();
    38     }
    39     memset(vis,0,sizeof(vis));
    40     memset(depth,0,sizeof(depth));
    41 }
    42 int main(){
    43     scanf("%d",&t);
    44     while(t--){
    45         scanf("%d",&n);
    46         init();
    47         int x, y;
    48         for(int i = 1; i < n; i ++){
    49             scanf("%d %d",&x,&y);
    50             G[x].push_back(y);
    51             G[y].push_back(x);
    52             vis[y] = 1;
    53         }
    54         for(int i = 1; i <= n; i ++){
    55             if(!vis[i]){
    56                 dfs(i,-1,0);
    57                 for(int k = 0; k+1 < 30; k ++){
    58                     for(int v = 0; v < N; v ++){
    59                         if(parent[k][v] < 0) parent[k+1][v] = -1;
    60                         else parent[k+1][v] = parent[k][parent[k][v]];
    61                     }
    62                 }
    63             }
    64         }
    65         scanf("%d%d",&x,&y);
    66         printf("%d
    ",lca(x,y));
    67     }
    68     return 0;
    69 }
  • 相关阅读:
    《构建高性能web站点》阅读笔记(三)
    哈希表的C实现(一)
    《大规模web服务开发技术》阅读笔记
    CentOS搭建python开发环境
    Instagram的技术探索(2)
    CentOS5.5编译安装gvim7.3 失败记录
    由于启动用户实例的进程时出错,导致无法生成 SQL Server 的用户实例。该连接将关闭
    wp开发中解决gb2312的编码问题
    WP8 SDK 视图设计器 未将对象设置到对象的实例解决方法
    Oracle误删表的恢复
  • 原文地址:https://www.cnblogs.com/xingkongyihao/p/7220946.html
Copyright © 2020-2023  润新知