[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 }