zoukankan      html  css  js  c++  java
  • poj 1330(RMQ&LCA入门题)

    传送门:Problem 1330

    https://www.cnblogs.com/violet-acmer/p/9686774.html

      

    参考资料:

      http://dongxicheng.org/structure/lca-rmq/

      挑战程序设计竞赛(第二版)

    变量解释:

      对有根树进行DFS,将遍历到的节点按照顺序记下,我们将得到一个长度为2N-1的序列,称之为欧拉序列。

      total : 记录dfs遍历过程中回溯的节点编号,其实就是从0->2N-1。

      vs[ ] : 记录DFS访问的顺序,也就是欧拉序列。

      depth[ ] : 记录访问到的节点的深度。

      pos[ ] : 记录各个顶点在va[ ] 中首次出现的下标。

    AC代码献上:

    基于RMQ的LCA

     1 #include<iostream>
     2 #include<vector>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<cstdio>
     6 using namespace std;
     7 #define pb(x) push_back(x)
     8 const int maxn=10010;
     9 
    10 int n;
    11 int total;
    12 int root;
    13 int vs[2*maxn-1];//最多需要记录 2*n-1个数
    14 int depth[2*maxn-1];
    15 int pos[maxn];
    16 vector<int >edge[maxn];
    17 
    18 //==========RMQ==========
    19 struct RMQ
    20 {
    21     int dp[20][2*maxn-1];
    22     void Pretreat()//预处理dp[0][]
    23     {
    24         for(int i=0;i < total;++i)
    25             dp[0][i]=i;
    26     }
    27     void ST()//ST表中记录的是使区间[i,j]的 depth[ ]值最小的下标,级dp[][]存储的是下标,而不是最小值
    28     {
    29         //欧拉序列中一共有total个数
    30         //2^k == total -> k=log2(total) (以2为底),但计算机中的log是以e为底的
    31         //由换底公式可得 k = log(total)/log(2)
    32         int k=log(total)/log(2);
    33         for(int i=1;i <= k;++i)
    34             for(int j=0;j <= (total-(1<<i));++j)
    35                 if(depth[dp[i-1][j]] > depth[dp[i-1][j+(1<<(i-1))]])
    36                     dp[i][j]=dp[i-1][j+(1<<(i-1))];//记录的是使depth[ ]最小的下标
    37                 else
    38                     dp[i][j]=dp[i-1][j];
    39     }
    40     int LCA(int u,int v)
    41     {
    42         if(u > v)
    43             swap(u,v);
    44         int k=log(v-u+1)/log(2);
    45         if(depth[dp[k][u]] > depth[dp[k][v-(1<<k)+1]])
    46             return vs[dp[k][v-(1<<k)+1]];
    47         return vs[dp[k][u]];
    48     }
    49 }_rmq;
    50 //=======================
    51 void Dfs(int v,int f,int d)
    52 {
    53     pos[v]=total;
    54     vs[total]=v;
    55     depth[total++]=d;
    56     for(int i=0;i < edge[v].size();++i)
    57     {
    58         int to=edge[v][i];
    59         if(to != f)
    60         {
    61             Dfs(to,v,d+1);
    62             vs[total]=v;
    63             depth[total++]=d;
    64         }
    65     }
    66 }
    67 void Init()
    68 {
    69     total=0;
    70     root=0;
    71     for(int i=1;i <= n;++i)
    72         edge[i].clear();
    73 }
    74 
    75 int main()
    76 {
    77     int T;
    78     scanf("%d",&T);
    79     while(T--)
    80     {
    81         scanf("%d",&n);
    82         Init();
    83         for(int i=1;i < n;++i)
    84         {
    85             int u,v;
    86             scanf("%d%d",&u,&v);
    87             edge[u].pb(v);
    88             root=(root == 0 || root == v ? u:root);
    89         }
    90         Dfs(root,-1,0);
    91         _rmq.Pretreat();
    92         _rmq.ST();
    93         int u,v;
    94         scanf("%d%d",&u,&v);
    95         printf("%d
    ",_rmq.LCA(pos[u],pos[v]));
    96     }
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    [转]:Android 5.0的调度作业JobScheduler
    Android 移动端数据结构
    算法-二分查找
    设计模式-设计原则
    设计模式-单例模式(Singleton Pattren)(饿汉模式和懒汉模式)
    Android 7.0 Dialog 无法显示的问题
    设计模式-装饰模式(Decorator Pattern)
    产品中心2
    java中static和final修饰符
    java访问修饰符
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9697883.html
Copyright © 2011-2022 走看看