1. 程式人生 > >【模板】樹上倍增求LCA

【模板】樹上倍增求LCA

參考題目:Tree

題目描述

給出一棵帶有邊權的樹,問兩點之間的距離。

輸入格式

第一行兩個整數 n 和 m ,分別表示點數和詢問數。
接下來 n-1 行,每行三個整數 x,y,z,表示 x 與 y 通過一條權為 z 的邊連線。
接下來 m 行,每行兩個整數 x,y,代表一組詢問。

輸出格式

輸出 m 行,每行一個整數,對應一組詢問的答案。

樣例資料

輸入

3 3
1 2 1
1 3 2
1 2
1 3
2 3

輸出

1
2
3

備註

【資料範圍】

對 30% 的輸入資料 :1≤n,m≤1000
對 100% 的輸入資料 :1≤n,m≤100000;1≤z≤10000

解析:

好早之前寫的板子了,什麼時候有人催我我就補一下解析吧。。。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define re register
#define ll long long

inline
int getint(){
	static int num,c;
	num=0;
	for(c=getchar();!isdigit(c);c=getchar());
	for(;isdigit(c);c=getchar())
	num=(num<<1)+(num<<3)+c-'0';
	return num;
}

inline
void outint(ll x)
{ if(x>9)outint(x/10); putchar(x%10+'0'); } ll dis[100001],w[200002]; int Last[100001],to[200002],nxt[200002],ecnt; int fa[100001][20]; int dep[100001]; int n,m; inline void addedge(int u,int v,int val){ nxt[++ecnt]=Last[u];Last[u]=ecnt;to[ecnt]=v;w[ecnt]=val; nxt[++ecnt]=Last[v];Last[v]=ecnt;to[ecnt]=u;w[ecnt]=val; } inline
void dfs(int u){ for(int re v,e=Last[u];e;e=nxt[e]){ if((v=to[e])==fa[u][0])continue; fa[v][0]=u; dep[v]=dep[u]+1; dis[v]=w[e]+dis[u]; dfs(v); } } inline void init(){ dep[1]=1; dfs(1); for(int re i=1;i<=17;++i) for(int re j=1;j<=n;++j) fa[j][i]=fa[fa[j][i-1]][i-1]; } inline int LCA(int u,int v){ if(dep[u]<dep[v])swap(u,v); for(int re i=17;i>=0;i--) if(dep[fa[u][i]]>=dep[v])u=fa[u][i]; if(u==v)return u; for(int re i=17;i>=0;--i) if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i]; return fa[u][0]; } int main(){ n=getint(); m=getint(); for(int i=1;i<n;++i){ int u=getint(); int v=getint(); int val=getint(); addedge(u,v,val); } init(); while(m--){ int u=getint(); int v=getint(); outint(dis[u]+dis[v]-dis[LCA(u,v)]*2); puts(""); } return 0; }