[hdu2586]How far away?(LCA)

题意:问树上两点之间的最短距离

解题关键:LCA模板题,在线做法,LCA->RMQ,用st表求解

这里是用first,rmq数组长度可以减半。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<iostream>
 7 typedef long long ll;
 8 using namespace std;  
 9 const int maxn=40010; 
10 const int maxm=25;  
11 int _pow[maxm],m,n;  
12 int head[maxn],tot;  
13 int ver[maxn*2],depth[maxn*2],first[maxn],dis[maxn],rmq[maxn*2][maxm],id;//5个数组,注意哪个需要乘2 
14 
15 inline int read(){
16     char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar());
17     int x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=(x<<3)+(x<<1)+ls-'0';
18     if(k=='-')x=0-x;return x;
19 }
20 
21 struct edge{
22     int to,w,nxt;  
23 }e[maxn*2];//链式前向星建树 
24 
25 void init(){
26     memset(head,-1,sizeof head);  
27     tot=0;
28     id=0;
29 }
30 
31 void add_edge(int u,int v,int w){  
32     e[tot].to=v;
33     e[tot].w=w;
34     e[tot].nxt=head[u];
35     head[u]=tot++;
36 }
37   
38 void dfs(int u,int fa,int dep){
39     ver[++id]=u;//第i个访问到的结点编号 
40     depth[id]=dep;//第i个访问到的结点深度  
41     first[u]=id;
42     for(int i=head[u];i!=-1;i=e[i].nxt){
43         int v=e[i].to;
44         int w=e[i].w;
45         if(v==fa) continue;
46         dis[v]=dis[u]+w;//dis是先序遍历求 
47         dfs(v,u,dep+1);
48         ver[++id]=u;//后序遍历,再次访问父节点 
49         depth[id]=dep;
50     }
51 } 
52   
53 void rmq_init(int n){  
54     int k=int(log(n)/log(2));  
55     for(int i=1;i<=n;i++)    rmq[i][0]=i;  
56     for(int j=1;j<=k;j++){  
57         for(int i=1;i+_pow[j]-1<=n;i++){//因为存的是索引 
58             int a=rmq[i][j-1],b=rmq[i+_pow[j-1]][j-1];  
59             if(depth[a]<depth[b])    rmq[i][j]=a;  
60             else  rmq[i][j]=b;  
61         }
62     }
63 }
64   
65 int rmq_query(int l,int r){
66     int k=int(log(r-l+1)/log(2));  
67     int a=rmq[l][k],b=rmq[r-_pow[k]+1][k];  
68     if(depth[a]<depth[b])  return a;  
69     else  return b;
70 }//返回的依然是索引 
71   
72 int LCA(int u,int v){
73     int x=first[u],y=first[v];  
74     if(x>y)swap(x,y);  
75     int res=rmq_query(x,y);  
76     return ver[res]; 
77 }
78 
79 int main(){
80     for(int i=0;i<maxm;i++)    _pow[i]=1<<i; //预处理2^n 
81     int t,a,b,c;
82     t=read();
83     while(t--){
84         init();
85         n=read();m=read();
86         for(int i=0;i<n-1;i++) a=read(),b=read(),c=read(),add_edge(a,b,c),add_edge(b,a,c);
87         dfs(1,-1,0);
88         rmq_init(2*n-1);
89         for(int i=0;i<m;i++){
90             a=read(),b=read();
91             int ans=LCA(a,b);
92             printf("%d\n",dis[a]+dis[b]-2*dis[ans]);
93         }
94     }
95     return 0;
96 }

 

posted @ 2017-09-03 14:09  Elpsywk  阅读(198)  评论(0编辑  收藏  举报