LCA - 求任意两点间的距离
There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
InputFirst line is a single integer T(T<=10), indicating the number of test cases.
For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.OutputFor each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.Sample Input
2 3 2 1 2 10 3 1 15 1 2 2 3 2 2 1 2 100 1 2 2 1Sample Output
10 25 100 100
题目分析 : 给出一些点之间的长度,再给出一些询问,查任意两点间的距离。
思路分析 : 倍增LCA裸题
代码示例 :
#define ll long long const int maxn = 4e4+5; const double pi = acos(-1.0); const int inf = 0x3f3f3f3f; int n, m, N; struct node { int to, cost; node(int _to = 0, int _cost = 0):to(_to),cost(_cost){} }; vector<node>ve[maxn]; int dep[maxn]; int grand[maxn][30], gw[maxn][30]; void dfs(int x, int fa){ for(int i = 1; i <= N; i++){ grand[x][i] = grand[grand[x][i-1]][i-1]; gw[x][i] = gw[x][i-1] + gw[grand[x][i-1]][i-1]; } for(int i = 0; i < ve[x].size(); i++){ int to = ve[x][i].to; int cost = ve[x][i].cost; if (to == fa) continue; dep[to] = dep[x] + 1; grand[to][0] = x; gw[to][0] = cost; dfs(to, x); } } int lca(int a, int b){ // a 是在 b 的上面的 if (dep[a] > dep[b]) swap(a, b); int ans = 0; for(int i = N; i >= 0; i--){ if (dep[a] < dep[b] && dep[grand[b][i]] >= dep[a]){ ans += gw[b][i]; b = grand[b][i]; } } // a, b 在同一层后 for(int i = N; i >= 0; i--){ if (grand[a][i] != grand[b][i]) { ans += gw[a][i]; ans += gw[b][i]; a = grand[a][i], b = grand[b][i]; } } if (a != b) { ans += gw[a][0]; ans += gw[b][0]; } return ans; } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int t; int a, b, c; cin >> t; while(t--){ scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) ve[i].clear(); for(int i = 1; i < n; i++){ scanf("%d%d%d", &a, &b, &c); ve[a].push_back(node(b, c)); ve[b].push_back(node(a, c)); } memset(grand, 0, sizeof(grand)); memset(gw, 0, sizeof(gw)); dep[1] = 0; N = floor(log(n)/log(2)); // 求出最大的2^k = N中的 k dfs(1, 1); for(int i = 1; i <= m; i++){ scanf("%d%d", &a, &b); printf("%d\n", lca(a, b)); } } return 0; } /* 5 8 100 1 2 1 2 4 1 2 5 1 2 6 1 1 3 1 3 7 1 1 8 1 */
东北日出西边雨 道是无情却有情