1. 程式人生 > >hdu2586 lca倍增法

hdu2586 lca倍增法

倍增法加了邊的權值,bfs的時候順便把每個點深度求出來即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define maxn 40005
#define DEG 20
struct Edge{
    int to,next,w;
}edge[maxn*2];
int head[maxn],tot;
void addedge(int u,int v,int w){
    edge[tot].to=v;
    edge[tot].next
=head[u]; edge[tot].w=w; head[u]=tot++; } int fa[maxn][DEG]; int deg[maxn],depth[maxn]; int flag[maxn]; void bfs(int root){ queue<int> que; deg[root]=0;depth[root]=0; fa[root][0]=root; que.push(root); while(!que.empty()){ int tmp=que.front();que.pop();
for(int i=1;i<DEG;i++) fa[tmp][i]=fa[fa[tmp][i-1]][i-1]; for(int i=head[tmp];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==fa[tmp][0])continue; deg[v]=deg[tmp]+1; depth[v]=depth[tmp]+edge[i].w; fa[v][0]=tmp; que.push(v); } } }
int lca(int u,int v){ if(deg[u]>deg[v]) swap(u,v); int hu=deg[u],hv=deg[v],tu=u,tv=v; for(int det=hv-hu,i=0;det;det>>=1,i++) if(det&1) tv=fa[tv][i]; if(tu==tv) return tu; for(int i=DEG-1;i>=0;i--){ if(fa[tu][i]==fa[tv][i]) continue; tu=fa[tu][i];tv=fa[tv][i]; } return fa[tu][0]; } void init(){ tot=0; memset(flag,0,sizeof flag); memset(head,-1,sizeof head); memset(deg,0,sizeof deg); memset(depth,0,sizeof depth); } int main(){ int T,n,q,u,v,w; cin >> T; while(T--){ init(); scanf("%d%d",&n,&q); for(int i=1;i<n;i++){ scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); flag[v]=1; } int root; for(int i=1;i<=n;i++) if(!flag[i]){root=i;break;} bfs(root); while(q--){ scanf("%d%d",&u,&v); int tmp=lca(u,v); printf("%d\n",depth[u]+depth[v]-2*depth[tmp]); } } return 0; }