Description
N頭牛(2<=n<=1000)別人被標記爲1到n,在同樣被標記1到n的n塊土地上吃草,第i頭牛在第i塊牧場吃草。
這n塊土地被n-1條邊連接。 奶牛可以在邊上行走,第i條邊連接第Ai,Bi塊牧場,第i條邊的長度是Li(1<=Li<=10000)。
這些邊被安排成任意兩頭奶牛都可以通過這些邊到達的情況,所以說這是一棵樹。
這些奶牛是非常喜歡交際的,經常會去互相訪問,他們想讓你去幫助他們計算Q(1<=q<=1000)對奶牛之間的距離。Input
*第一行:兩個被空格隔開的整數:N和Q
*第二行到第n行:第i+1行有兩個被空格隔開的整數:AI,BI,LI
*第n+1行到n+Q行:每一行有兩個空格隔開的整數:P1,P2,表示兩頭奶牛的編號。
Output
*第1行到第Q行:每行輸出一個數,表示那兩頭奶牛之間的距離。
Sample Input
4 2
2 1 2
4 3 2
1 4 3
1 2
3 2
Sample Output
2
7
HINT
Source
資格賽
lca
#include <iostream>
#include <cstdio>
using namespace std;
const int SZ = 1010;
struct Edge
{
int f, t, d;
}es[SZ << 1];
int first[SZ << 1], nxt[SZ << 1], tot = 1;
int depth[SZ], fa[SZ], dis[SZ], jump[SZ][20];
void build(int f, int t, int d)
{
es[++tot] = (Edge){f, t ,d};
nxt[tot] = first[f];
first[f] = tot;
}
void dfs(int u, int f)
{
depth[u] = depth[f] + 1;
fa[u] = f;
jump[u][0] = f;
for(int i = 1; i <= 16; i++)
jump[u][i] = jump[jump[u][i - 1]][i - 1];
for(int i = first[u]; i; i = nxt[i])
{
int v = es[i].t;
if(v == f) continue;
dis[v] = dis[u] + es[i].d;
dfs(v, u);
}
}
int lca(int l, int r)
{
if(depth[l] < depth[r]) swap(l, r);
int t = depth[l] - depth[r];
for(int i = 0; i <= 16; i++)
if(t & (1 << i)) l = jump[l][i];
for(int i = 16; i >= 0; i--)
if(jump[l][i] != jump[r][i])
l = jump[l][i], r = jump[r][i];
if(l == r) return l;
return jump[l][0];
}
int main()
{
int n, q;
scanf("%d%d", &n, &q);
int f, t, d;
for(int i = 1; i < n; i++)
{
scanf("%d%d%d", &f, &t, &d);
build(f, t, d);
build(t, f, d);
}
dfs(1, 0);
for(int i = 1; i <= q; i++)
{
scanf("%d%d", &f, &t);
int F = lca(f, t);
int ans = dis[f] + dis[t] - 2 * dis[F];
printf("%d\n", ans);
}
return 0;
}