LCA距离

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(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.

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

n个定点,每个点之间有距离,q次询问,求两点之间的最短路径,和最小生成树有所不同的是n个定点只有n-1个边使之相通,没有连成圆。

用LCA做时,连点之间的距离等于根节点到两点距离之和 减去根节点到点v点的祖先的距离的两倍 即ans[query[u][i].w] = dis[u]+dis[v]-2*dis[findset(v)];

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <vector>
 5 using namespace std;
 6 const int N = 40010;
 7 struct Nod{
 8     int to, w;
 9     Nod(int a = 0, int b = 0){
10         to = a; w = b;
11     }
12 };
13 int ans[N];
14 int par[N],vis[N],mark[N],dis[N];
15 int n,m;
16 vector<Nod> mp[N];
17 vector<Nod> query[N];
18 void init(){
19     for(int i = 0; i <= n; i ++){
20         mp[i].clear();
21         query[i].clear();
22         vis[i] = mark[i] = 0;
23         par[i] = i;
24     }
25     memset(ans,-1,sizeof(ans));
26 }
27 int findset(int x){
28     if(x != par[x]) par[x] = findset(par[x]);
29     return par[x];
30 }
31
32 void dfs(int u){
33     for(int i = 0; i < query[u].size(); i ++){
34         int v = query[u][i].to;
35         if(vis[v]&&ans[query[u][i].w]==-1&&!mark[findset(v)]){
36             ans[query[u][i].w] = dis[u]+dis[v]-2*dis[findset(v)];
37         }
38     }
39     for(int i = 0; i < mp[u].size(); i++){
40         int v = mp[u][i].to;
41         if(!vis[v]){
42             vis[v] = 1;
43             dis[v] = dis[u]+mp[u][i].w;
44             dfs(v);
45             par[v] = u;
46         }
47     }
48 }
49
50 int main(){
51     int t;
52     scanf("%d",&t);
53     while(t--){
54         scanf("%d%d",&n,&m);
55         init();
56         int x, y, z;
57         for(int i = 0; i < n-1; i ++){
58             scanf("%d%d%d",&x,&y,&z);
59             mp[x].push_back(Nod(y,z));
60             mp[y].push_back(Nod(x,z));
61         }
62         for(int i = 1; i <= m; i ++){
63             scanf("%d%d",&x,&y);
64             query[x].push_back(Nod(y,i));
65             query[y].push_back(Nod(x,i));
66         }
67         for(int i = 1; i <= n; i ++){
68             if(!vis[i]){
69                 printf("%d+++\n",i);
70                 vis[i] = 1;
71                 dis[i] = 0;
72                 dfs(i);
73                 mark[i] = 1;
74             }
75         }
76         for(int i = 1; i <= m; i ++){
77             printf("%d\n",ans[i]);
78         }
79     }
80     return 0;
81 }
时间: 2024-08-17 17:33:54

LCA距离的相关文章

Codefources 519E. A and B and Lecture Rooms LCA

简单LCA: 求树上距离给定两个点a,b距离相等的点有多少个 先预处理出每个节点的孩子个数sum[x],求出a,b的LCA,根据深度就可以知道两个点的距离,距离为偶数的有解.... 根据lca在a,b之间的位置不同分情况讨论: 设a与lca距离为 ha , b与lca距离为 hb 1:lca在a,b正中间既a,b分别属于lca的两个子树中, 结果为: n-sum[ a往上距离lca ha-1 的点] - sum[ b往上距离lca hb-1 的点] 2:a,b两个点相对lca一上一下. c:a,

HDU 2586 How far away ?(LCA模板 近期公共祖先啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 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

HDU 2586 How far away ?(LCA模板 最近公共祖先啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 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

Codeforces Round #629 (Div. 3) E. Tree Queries(LCA)

https://codeforces.com/contest/1328/problem/E 题目所描述的是一棵树,题中已明示1为root结点. 题目可以转化为,是否存在一条路径,满足集合中的k个点到路径的距离小于等于1? 思路: 1.首先倍增离线预处理出结点深度,便于后续在线询问LCA 2.对于每次的询问,依次扫描k个点.对于集合中的u和v两点,每次我们求出u和v的LCA,计算u和v到LCA的距离,如果u和v到LCA的距离同时大于1,那么说明无法找到一条路径,使得u和v到该路径链的距离小于等于1

cf 700 B Connecting Universities

题意:现在给以一棵$n$个结点的树,并给你$2k$个结点,现在要求你把这些节点互相配对,使得互相配对的节点之间的距离(路径上经过边的数目)之和最大.数据范围$1 \leq n \leq 200000, 2k \leq n$. 分析:贪心选择距离最大.次大...的结点对?貌似不对.暴力枚举所有可能?对但不可行.考虑节点对之间的距离实际上就是它们到LCA距离之和.因此单独考虑每个结点,它对答案的贡献实际上就是它到与其匹配节点的LCA的距离,这个距离必然不超过它到根的距离.如果我们有一种方法使得每个结

[UOJ]#33. 【UR #2】树上GCD

题目大意:给定一棵有根树,边长均为1,对于每一个i,求树上有多少个点对,他们到lca距离的gcd是i.(n<=200,000) 做法:先容斥,求出gcd是i的倍数的点对,考虑长链剖分后从小到大合并计算答案,小的部分先把每个深度的数量变为每个深度的倍数的数量,然后若深度>k,直接到大的里面暴力,若深度<=k,我们在大的里面维护f[i][j]表示深度mod i(1<=i<=k)为j的点数,理论上k取n^0.5时达到最小复杂度O(n^1.5),实际上k比较小的时候常数较小.另外递归

8.13联考题解

最长上升子串 时间限制: 2 Sec  内存限制: 64 MB 样例输入 67 2 3 1 5 6 样例输出 5 题解       刚一读题觉得和昨天T3相似度极高,只不过是久违的子串.还是想动归思路,f[i][1/0]表示到第i位是/否已经改变过序列的值,然后大概就是个择优转移的思路:受到昨天那题局限用一个辅助数组记录了一下改变后的值,贪心策略把它设为a[i-1][0]+1,.开始上手打,代码倒是很短,怎么想怎么觉得不对劲,自己凭着感觉开始刻意造数据卡这个做法.试了几组数之后成功用123745

2017/8/13 考试吐槽

2017 8 13 得分:160 联考最后一天--因为不会对拍日常爆炸-- A.最长上升子串 题意:给出一个序列,允许修改一次元素,求出这个序列最长子串. 这个玩意我刚开始以为是个线性$DP$,然后--细节巨多,写出来之后出一个数据卡一个-- 慌得我直喝水直上厕所--然后转到第$8$趟的时候,由于厕所比我在的那个窝风角落凉快,我的脑子算是冷静了下来,仔细一想,卧槽这不是$DP$!我可以先正序求出以每个元素开头子串长度,再倒序求出每个元素结尾子串长度,之后枚举修改位置,检查修改效果!$mdzz$-

UESTC 912 树上的距离 --LCA+RMQ+树状数组

1.易知,树上两点的距离dis[u][v] = D[u]+D[v]-2*D[lca(u,v)] (D为节点到根节点的距离) 2.某条边<u,v>权值一旦改变,将会影响所有以v为根的子树上的节点到根节点的距离,很明显,DFS一遍后以v为根的子树在DFS序列中是连续的一段,及转化为区间更新问题,可以用树状数组. 做法:先把求LCA解决,LCA可以转化为RMQ问题,可参见:LCA转RMQ, 即转化为LCA(T,u,v) = RMQ(B,pos[u],pos[v]),其中B为深度序列.预先DFS可以处