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\n",dist[u]+dist[v]-2*dist[lca]);
106         }
107     }
108     return 0;
109 }
基于RMQ的LCA

 

posted @ 2018-09-21 15:27  HHHyacinth  阅读(183)  评论(0编辑  收藏  举报