hdu2586 lca倍增法
阿新 • • 發佈:2018-11-25
倍增法加了邊的權值,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; }