[bzoj 1602] [Usaco2008 Oct]牧场行走

求树上两点的距离

裸LCA 用了倍增

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=1233;
 7 int n,q,cnt;
 8 int last[maxn],deep[maxn],dist[maxn];
 9 int f[maxn][20];
10 bool vis[maxn];
11 struct graph{
12     int to,next,weight;
13 }e[maxn*2];
14 void insert(int u,int v,int w){
15     e[++cnt].to=v;
16     e[cnt].weight=w;
17     e[cnt].next=last[u];
18     last[u]=cnt;
19 }
20 void dfs(int x){
21     vis[x]=1;
22     for (int i=1;(1<<i)<=deep[x];i++)
23         f[x][i]=f[f[x][i-1]][i-1];
24     for (int i=last[x];i;i=e[i].next)
25         if (!vis[e[i].to]){
26             int now=e[i].to;
27             deep[now]=deep[x]+1;
28             dist[now]=dist[x]+e[i].weight;
29             f[now][0]=x;
30             dfs(now);
31         }
32 }
33 int lca(int x,int y){
34     if (deep[x]<deep[y]) swap(x,y);
35     int d=deep[x]-deep[y];
36     for (int i=0;(1<<i)<=d;i++)
37        if ((1<<i)&d) x=f[x][i];
38     if (x==y) return x;
39     for (int i=10;i>=0;i--)
40       if (f[x][i]!=f[y][i])
41         x=f[x][i],y=f[y][i];
42     return f[x][0];
43 }
44 int main(){
45     scanf("%d%d",&n,&q);
46     memset(dist,0,sizeof(dist));
47     int u,v,w;
48     for (int i=1;i<n;i++){
49         scanf("%d%d%d",&u,&v,&w);
50         insert(u,v,w),insert(v,u,w);
51     }
52     dfs(1);
53     for (int i=1;i<=q;i++){
54         scanf("%d%d",&u,&v);
55         printf("%d\n",dist[u]+dist[v]-2*dist[lca(u,v)]);
56     }
57     return 0;
58 }
View Code

 

posted @ 2017-08-14 16:14  Vincent_hwh  阅读(84)  评论(0编辑  收藏  举报