zoukankan      html  css  js  c++  java
  • hdu 2586(裸LCA)

    传送门

    题意:

      某村庄有n个小屋,n-1条道路连接着n个小屋(无环),求村庄A到村庄B的距离,要求是经过任一村庄不超过一次。

    题解:

      求出 lca = LCA(u,v) , 然后答案便是dist[u] + dist[v] - 2 * dist[lca];

    AC代码:

      1 #include<iostream>
      2 #include<vector>
      3 #include<cstdio>
      4 #include<cmath>
      5 #include<cstring>
      6 using namespace std;
      7 #define pb(x) push_back(x)
      8 #define mem(a,b) memset(a,b,sizeof(a))
      9 const int maxn=4e4+50;
     10 
     11 int n,q;
     12 int dist[maxn];//dist[i]: 节点i与节点1的距离,假定1为根节点
     13 int vs[2*maxn];//欧拉序列
     14 int depth[2*maxn];//深度序列
     15 int pos[maxn];//pos[i]:节点i在欧拉序列中第一次出现的位置
     16 bool vis[maxn];
     17 struct Edge
     18 {
     19     int to;
     20     int w;
     21     Edge(int a=0,int b=0):to(a),w(b){}
     22 };
     23 vector<Edge >G[maxn];
     24 void addEdge(int u,int v,int w)
     25 {
     26     G[u].pb(Edge(v,w));
     27 }
     28 struct RMQ
     29 {
     30     int dp[31][2*maxn];
     31     void rmq()
     32     {
     33         int tot=2*n-1;
     34         for(int i=1;i <= tot;++i)
     35             dp[0][i]=i;
     36         for(int k=1;(1<<k) <= tot;++k)
     37             for(int i=1;((1<<k)+i-1) <= tot;++i)
     38                 if(depth[dp[k-1][i]] > depth[dp[k-1][i+(1<<(k-1))]])
     39                     dp[k][i]=dp[k-1][i+(1<<(k-1))];
     40                 else
     41                     dp[k][i]=dp[k-1][i];
     42     }
     43     int lca(int u,int v)
     44     {
     45         u=pos[u],v=pos[v];
     46         if(u > v)
     47             swap(u,v);
     48         int k=log(v-u+1)/log(2);
     49         return vs[min(dp[k][u],dp[k][v-(1<<k)+1])];
     50     }
     51 }_rmq;
     52 void Dfs(int u,int dis,int dep,int &k)
     53 {
     54     vs[++k]=u;
     55     depth[k]=dep;
     56     pos[u]=k;
     57     dist[u]=dis;
     58     vis[u]=true;
     59     for(int i=0;i < G[u].size();++i)
     60     {
     61         int to=G[u][i].to;
     62         int w=G[u][i].w;
     63         if(!vis[to])
     64         {
     65             Dfs(to,dis+w,dep+1,k);
     66             vs[++k]=u;
     67             depth[k]=dep;
     68         }
     69     }
     70 }
     71 void LCA()
     72 {
     73     int k=0;
     74     Dfs(1,0,0,k);
     75     _rmq.rmq();
     76 }
     77 void Init()
     78 {
     79     mem(vis,false);
     80     for(int i=1;i <= n;++i)
     81         G[i].clear();
     82 }
     83 int main()
     84 {
     85 //    freopen("C:/Users/hyacinthLJP/Desktop/stdin/hdu2586.txt","r",stdin);
     86     int t;
     87     scanf("%d",&t);
     88     while(t--)
     89     {
     90         Init();
     91         scanf("%d%d",&n,&q);
     92         for(int i=1;i < n;++i)
     93         {
     94             int u,v,w;
     95             scanf("%d%d%d",&u,&v,&w);
     96             addEdge(u,v,w);
     97             addEdge(v,u,w);
     98         }
     99         LCA();
    100         for(int i=1;i <= q;++i)
    101         {
    102             int u,v;
    103             scanf("%d%d",&u,&v);
    104             int lca=_rmq.lca(u,v);
    105             printf("%d
    ",dist[u]+dist[v]-2*dist[lca]);
    106         }
    107     }
    108     return 0;
    109 }
    基于RMQ的LCA
  • 相关阅读:
    Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2) E. The Supersonic Rocket
    Codeforces Round #500 (Div. 2) D
    AtCoder Grand Contest 026 D
    Codeforces Round #495 (Div. 2) Sonya and Matrix
    AtCoder Regular Contest 100 E
    1013 数素数
    1010 一元多项式求导(用while接收输入)
    1009 说反话(字符串、栈)
    L2-006 树的遍历 (后序中序求层序)
    L2-004 这是二叉搜索树吗?
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9686780.html
Copyright © 2011-2022 走看看