zoukankan      html  css  js  c++  java
  • HDU 2586 LCA

     题目大意:

    多点形成一棵树,树上边有权值,给出一堆询问,求出每个询问中两个点的距离

    这里求两个点的距离可以直接理解为求出两个点到根节点的权值之和,再减去2倍的最近公共祖先到根节点的距离

    这是自己第一道lca题目

    学习了两种方法

    第一种在ST算法,利用RMQ思想预处理

     1 /*在线ST算法*/
     2 #pragma comment(linker, "/STACK:102400000,102400000")
     3 #include <cstdio>
     4 #include <iostream>
     5 #include <cstring>
     6 #include <algorithm>
     7 using namespace std;
     8 #define N 40010
     9 
    10 int first[N] , k;
    11 
    12 struct Edge{
    13     int x , y , w , next;
    14     Edge(){}
    15     Edge(int x , int y , int w , int next):x(x),y(y),w(w),next(next){}
    16 }e[N<<1];
    17 
    18 void add_edge(int x , int y , int w)
    19 {
    20     e[k] = Edge(x , y , w , first[x]);
    21     first[x] = k++;
    22 }
    23 int dp[N<<1][28];
    24 int id[N<<1] , dep[N<<1] , dis[N] , No[N] , dfs_clock;
    25 void dfs(int u , int f , int d)
    26 {
    27     id[++dfs_clock] = u , No[u] = dfs_clock , dep[dfs_clock] = d;
    28     for(int i=first[u] ; ~i ; i=e[i].next){
    29         int v = e[i].y;
    30         if(v == f) continue;
    31         dis[v] = dis[u]+e[i].w;
    32         dfs(v , u , d+1);
    33         id[++dfs_clock] = u , dep[dfs_clock] = d;
    34     }
    35 }
    36 
    37 void ST(int n)
    38 {
    39     for(int i=1 ; i<=n ; i++) dp[i][0] = i;
    40     for(int j=1 ; (1<<j)<=n ; j++){
    41         for(int i=1 ; i+(1<<j)-1<=n ; i++){
    42             int a = dp[i][j-1] , b = dp[i+(1<<(j-1))][j-1];
    43             dp[i][j] = dep[a]<dep[b]?a:b;
    44         }
    45     }
    46 }
    47 
    48 int RMQ(int l , int r)
    49 {
    50     int k=0;
    51     while((1<<(k+1))<=r-l+1) k++;
    52     int a = dp[l][k] , b = dp[r-(1<<k)+1][k];
    53     return dep[a]<dep[b]?a:b;
    54 }
    55 
    56 int LCA(int u , int v)
    57 {
    58     int x = No[u] , y = No[v];
    59     if(x>y) swap(x , y);
    60     return id[RMQ(x , y)];
    61 }
    62 
    63 int n , m;
    64 
    65 int main()
    66 {
    67    // freopen("in.txt" , "r" , stdin);
    68     int T , x , y , w;
    69     scanf("%d" , &T);
    70     while(T--)
    71     {
    72         scanf("%d%d" , &n , &m);
    73         memset(first , -1 , sizeof(first));
    74         k = 0;
    75         for(int i=1 ; i<n ; i++){
    76             scanf("%d%d%d" , &x , &y , &w);
    77             add_edge(x , y , w);
    78             add_edge(y , x , w);
    79         }
    80         dfs_clock = 0;
    81         dis[1] = 0;
    82         dfs(1 , 0 , 1);
    83         ST(2*n-1);
    84         while(m--){
    85             scanf("%d%d" , &x , &y);
    86             int anc = LCA(x , y);
    87             printf("%d
    " , dis[x]-2*dis[anc]+dis[y]);
    88         }
    89     }
    90     return 0;
    91 }
    ST算法

    第二种是离线的Tarjan算法,利用并查集的思想解决

     1 /*在线ST算法*/
     2 #pragma comment(linker, "/STACK:102400000,102400000")
     3 #include <cstdio>
     4 #include <iostream>
     5 #include <cstring>
     6 #include <algorithm>
     7 using namespace std;
     8 #define N 40010
     9 #define M 205
    10 int first[N] , k;
    11 
    12 struct Edge{
    13     int x , y , w , next;
    14     Edge(){}
    15     Edge(int x , int y , int w , int next):x(x),y(y),w(w),next(next){}
    16 }e[N<<1];
    17 
    18 int _first[N] , _k;
    19 
    20 struct Que{
    21     int v , lca , next;
    22     Que(){}
    23     Que(int v , int lca , int next):v(v),lca(lca),next(next){}
    24 }eq[M<<1];
    25 
    26 void add_edge(int x , int y , int w)
    27 {
    28     e[k] = Edge(x , y , w , first[x]);
    29     first[x] = k++;
    30 }
    31 
    32 void add_que_edge(int x , int y)
    33 {
    34     eq[_k] = Que(y , 0 , _first[x]);
    35     _first[x] = _k++;
    36 }
    37 
    38 int fa[N] , dis[N];
    39 bool vis[N];
    40 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    41 
    42 void tarjan(int u)
    43 {
    44     vis[u] = true , fa[u] = u;
    45     for(int i=first[u] ; ~i ; i=e[i].next){
    46         int v = e[i].y;
    47         if(vis[v]) continue;
    48         dis[v] = dis[u]+e[i].w;
    49         tarjan(v);
    50         fa[v] = u;
    51     }
    52     for(int i=_first[u] ; ~i ; i=eq[i].next){
    53         int v = eq[i].v;
    54         if(vis[v]) eq[i].lca = eq[i^1].lca = find(eq[i].v);
    55     }
    56 }
    57 int n , m;
    58 
    59 int main()
    60 {
    61    // freopen("in.txt" , "r" , stdin);
    62     int T , x , y , w;
    63     scanf("%d" , &T);
    64     while(T--)
    65     {
    66         scanf("%d%d" , &n , &m);
    67         memset(first , -1 , sizeof(first));
    68         k = 0;
    69         for(int i=1 ; i<n ; i++){
    70             scanf("%d%d%d" , &x , &y , &w);
    71             add_edge(x , y , w);
    72             add_edge(y , x , w);
    73         }
    74         memset(_first , -1 , sizeof(_first));
    75         _k = 0;
    76         for(int i=0 ; i<m ; i++){
    77             scanf("%d%d" , &x , &y);
    78             add_que_edge(x , y);
    79             add_que_edge(y , x);
    80         }
    81         memset(vis , 0 , sizeof(vis));
    82         tarjan(1);
    83         for(int i=0 ; i<m*2 ; i+=2){
    84             int lca = eq[i].lca;
    85             printf("%d
    " , dis[eq[i].v]-2*dis[lca]+dis[eq[i^1].v]);
    86         }
    87     }
    88     return 0;
    89 }
    Tarjan算法
  • 相关阅读:
    移动开发 Native APP、Hybrid APP和Web APP介绍
    urllib与urllib2的学习总结(python2.7.X)
    fiddler及postman讲解
    接口测试基础
    UiAutomator2.0 和1.x 的区别
    adb shell am instrument 命令详解
    GT问题记录
    HDU 2492 Ping pong (树状数组)
    CF 567C Geometric Progression
    CF 545E Paths and Trees
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4712771.html
Copyright © 2011-2022 走看看