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算法
  • 相关阅读:
    Tomcat 中会话超时的相关配置
    Oracle10g任务调度创建步骤
    Oracle的三种高可用集群方案
    软/硬件负载均衡产品 你知多少?
    Nginx、LVS及HAProxy负载均衡软件的优缺点详解
    java.sql.SQLException: ORA-00604: 递归 SQL 级别 1 出现错误
    TortoiseSVN客户端重新设置用户名和密码
    Linux下oracle数据库启动和关闭操作
    Linux下使用ps命令来查看Oracle相关的进程
    【Kill】两条Linux命令彻底杀死Oracle
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4712771.html
Copyright © 2011-2022 走看看