【37.48%】【hdu 2587】How far away ?(3篇文章,3种做法,LCA之树上倍增)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 13390 Accepted Submission(s): 5018
Problem Description
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.
Input
First 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(0k<=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.
Output
For 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 1
Sample Output
10
25
100
100
【题解】
设p[i][j]表示i往上走2^j个节点到达的节点。
p[i][j]=p[p[i][j-1]][j-1];
然后先让所求的两个点的高度一样。
即高度高的一直往上走走到和高度底的高度一样;
然后再一起往上走走到共同的祖先;(最近);
找到祖先后输出dis[x]+dis[y]-2*dis[LCA];就是距离了。
这个距离是树上的最短距离。还是很有用的。可以扩展下;
#include <cstdio> #include <vector> #include <iostream> #include <algorithm> using namespace std; const int MAXN = 50000; const int MAX = 16; vector <int> son[MAXN],w[MAXN]; int n,p[MAXN][MAX+5],dep[MAXN],pre[MAX+5],m; long long dis[MAXN]; void input(int &r) { char t = getchar(); while (!isdigit(t)) t = getchar(); r = 0; while (isdigit(t)) r = r * 10 + t - '0', t = getchar(); } void dfs(int x,int f) { dep[x] = dep[f] + 1; p[x][0] = f; for (int i = 1; i <= MAX; i++) p[x][i] = p[p[x][i - 1]][i - 1]; int len = son[x].size(); for (int i = 0; i <= len - 1; i++) { int y = son[x][i]; if (y != f) { dis[y] = dis[x] + w[x][i]; dfs(y, x); } } } int main() { //freopen("F:\\rush.txt", "r", stdin); pre[0] = 1; for (int i = 1; i <= MAX; i++) pre[i] = pre[i - 1] << 1; int T; input(T); while (T--) { input(n); input(m); for (int i = 1; i <= n; i++) son[i].clear(),w[i].clear(); for (int i = 1; i <= n - 1; i++) { int x, y, z; input(x); input(y); input(z); son[x].push_back(y); w[x].push_back(z); son[y].push_back(x); w[y].push_back(z); } dis[1] = 0; dfs(1, 0); for (int i = 1; i <= m; i++) { int t0, t1,pret0,pret1; input(t0); input(t1); pret0 = t0; pret1 = t1; if (dep[t0] > dep[t1]) swap(t0, t1); for (int i = MAX; i >= 0; i--) if (dep[t0] <= dep[t1] - pre[i]) t1 = p[t1][i]; if (t1 == t0) { printf("%I64d\n",dis[pret0]+dis[pret1]-2*dis[t0]); continue; } for (int i = MAX; i >= 0; i--) { if (p[t0][i] == p[t1][i]) continue; t0 = p[t0][i], t1 = p[t1][i]; } printf("%I64d\n", dis[pret0]+dis[pret1]-2*dis[p[t0][0]]); } } return 0; }
- 【37.48%】【hdu 2587】How far away ?(3篇文章,3种做法,LCA之ST算法(RMQ))
- 【37.48%】【hdu 2587】How far away ?(3篇文章,3种做法,LCA之Tarjan算法)
- HDU-2586-How far away ?(倍增求LCA模板)
- HDU - 2586 How far away ?(LCA tarjan离线做法)
- hdu 2586 How far away ?(倍增法LCA)
- 【HDU】2586 How far away ? LCA求树上点对最近距离
- HDU - 2586 How far away ?(tarjan离线做法求lca)
- HDU 2586 How far away (LCA模板题 树上点对间距离)
- HDU - 2586 How far away (lca 倍增)
- How far away ? HDU - 2586(倍增实现的LCA)
- Hdu 2586 How far away ?【倍增LCA模板记录】
- 【HDU 2586 How far away?】LCA问题 Tarjan算法
- How far away ? HDU - 2586 tarjan求LCA
- hdu 2586 How far away ?(LCA:最近公共祖先)
- hdu 2586 How far away ? 【图论-邻接表-图转树-Lca】
- HDU 2586 How far away ?【LCA】
- hdu 2586 How far away ?(在线LCA+离线Tarjan)
- HDU 2586 How Far Away?(Tarjan离线算法求lca)
- How far away ? HDU - 2586 tarjan求LCA
- HDU 2586 How far away ? (LCA最近公共祖先)