HDOJ 2586 How far away? LCA

http://acm.hdu.edu.cn/showproblem.php?pid=2586

题意:

给一棵树,多次查询点到点距离。

分析:

d[x][y] = d[x][root] + d[y][root] - 2 * d[lca(x,y)][root],所以求lca即可。因为tarjan是在dfs的过程中求lca,顺便就把点到根的距离也求了。

敲了代码才发现,讲解的伪代码都是先递归子节点,染色,再回答询问的顺序,但是平时写的时候一般是建了双向边,先递归子节点再染色会导致环的情况从而死循环。所以网上的题解大多是先染色,再查询,再递归子节点。不过我试了一下,至少这一题,先染色,然后先回答询问或是先递归子节点都是可以AC的。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 using namespace std;
 6
 7 typedef pair<int, int> P;
 8 const int maxn = 40100;
 9
10 int T, n, m, x, y, z;
11 int f[maxn], d[maxn], ans[300];
12 bool vis[maxn];
13 vector<P> e[maxn], q[maxn];
14
15 int getf(int x)
16 {
17     if (f[x] == x) return x;
18     return f[x] = getf(f[x]);
19 }
20 void unionxy(int x, int y)
21 {
22     int xroot = getf(x), yroot = getf(y);
23     f[yroot] = xroot;
24 }
25 void tarjan(int x)
26 {
27     f[x] = x;
28     vis[x] = true;
29     for (int i = 0; i < q[x].size(); i++){
30         int v = q[x][i].first, id = q[x][i].second;
31         if (vis[v]){
32             int lca = f[getf(v)];
33             ans[id] = d[x] + d[v] - 2 * d[lca];
34         }
35     }
36     for (int i = 0; i < e[x].size(); i++){
37         int v = e[x][i].first, w = e[x][i].second;
38         if (!vis[v]){
39             d[v] = d[x] + w;
40             tarjan(v);
41             unionxy(x, v);
42             f[getf(x)] = x;
43         }
44     }
45 }
46 int main()
47 {
48     scanf("%d", &T);
49     while(T--)
50     {
51         scanf("%d %d", &n, &m);
52         for (int i = 0; i <= n; i++){
53             q[i].clear(); e[i].clear();
54         }
55         for (int i = 1; i < n; i++){
56             scanf("%d%d%d", &x, &y, &z);
57             e[x].push_back(make_pair(y, z));
58             e[y].push_back(make_pair(x, z));
59         }
60         for (int i = 0; i < m; i++){
61             scanf("%d %d", &x, &y);
62             if (x == y) ans[i] = 0;
63             else{
64                 q[x].push_back(make_pair(y, i));
65                 q[y].push_back(make_pair(x, i));
66             }
67         }
68         memset(vis, 0, sizeof(vis));
69         d[1] = 0;
70         tarjan(1);
71         for (int i = 0; i < m; i++)
72             printf("%d\n", ans[i]);
73     }
74     return 0;
75 }

HDOJ 2586 How far away? LCA

时间: 2024-10-11 17:08:52

HDOJ 2586 How far away? LCA的相关文章

hdoj 2586 How far away ? 【Tarjan离线LCA】

题目:hdoj 2586 How far away ? 题意:给出一个有权树,求任意两点的之间的距离. 分析:思想就是以一个点 root 作为跟变成有根数,然后深搜处理处所有点到跟的距离.求要求的两个点的LCA(最近公共祖先), 然后ans = dis[x] + dis[y] - 2 * dis[LCA(x,y)],可以画图分析一下就知道. 求LCA我用的是Tarjan离线lca,由于询问次数很多,所以这个比较快. AC代码: #include <iostream> #include <

Hdoj 2586 How far away ? 【LCA】

How far away ? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 7072 Accepted Submission(s): 2575 Problem Description There are n houses in the village and some bidirectional roads connecting them.

HDOJ 5293 Tree chain problem LCA+树链剖分+树形DP

[题意] 给定一颗树上的几条链和每条链的权值,求能取出的不含有公共节点的链的最大权值.... [解] 预处理每条链的lca 树形DP, d[i]表示取到这个节点时可以得到的最大值 , sum[i]=sigma( d[k] | k 是i的子节点) 如果不取i  d[i]=sum[i] 如果取i , e是lca为i的链则 d[i]=max(d[i],e的权值+sigma(sum[k])-sigma(d[k]))  k为树链上的点 可以用树链剖分+树装数组在nlogn的时间复杂度内求链上的值 Tree

HDU 2586 How far away LCA的离线算法 Tarjan

链接: How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11204    Accepted Submission(s): 4079 Problem Description There are n houses in the village and some bidirectional roads connec

LCA在线算法ST算法

求LCA(最近公共祖先)的算法有好多,按在线和离线分为在线算法和离线算法. 离线算法有基于搜索的Tarjan算法较优,而在线算法则是基于dp的ST算法较优. 首先说一下ST算法. 这个算法是基于RMQ(区间最大最小值编号)的,不懂的可以这里学习一些 而求LCA就是把树通过深搜得到一个序列,然后转化为求区间的最小编号. 比如说给出这样一棵树. 我们通过深搜可以得到这样一个序列: 节点ver 1 3 1 2 5 7 5 6 5 2 4 2 1 (先右后左) 深度R 1 2 1 2 3 4 3 4 3

屁股痛#4

A http://codeforces.com/problemset/problem/527/C 对一个矩形进行横和纵两种方向的分割 求每次分割后最大碎片的面积 用一个set记录分割线的位置 用一个可重复set记录线段的长度 用容器自带的二分找到位置并更新新的位置和长度 容器内部是有序的 取最后一个元素相乘即为最大 http://paste.ubuntu.com/25124870/ 需要学习的地方:STL是很强大的工具 在需要做一些复杂工作的时候记得考虑是否能用STL来简化操作 B http:/

HDOJ 题目2586 How far away ?(LCA)

How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 7090    Accepted Submission(s): 2578 Problem Description There are n houses in the village and some bidirectional roads connecting

LCA(最近公共祖先)--tarjan离线算法 hdu 2586

HDU 2586 How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11320    Accepted Submission(s): 4119 Problem Description There are n houses in the village and some bidirectional roads c

HDU 2586 LCA模板题

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2586 题目大意:在一个无向树上,求一条链权和. 解题思路: 0 | 1 /   \ 2      3 设dist[i]为i到根0的链和,求法(Dfs过程中dist[v]=dist[u]+e[i].w) 对于树中任意两点形成的链,可以通过LCA最近公共祖先剖分. 比如2->3,就可以经过LCA点1:  2->1->3 链和=dist[u]+dist[v]-2*dist[LCA[u,v]] (