【模板】樹上倍增求LCA
阿新 • • 發佈:2019-01-06
參考題目: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;
}