HDU 2586 How far away ? << LCA+tarjin求树上任两点最短距离裸题

题意

给你一棵树和每条边的权值,m次询问,求任两点间距离,LCA+tarjin裸题。

思路

能用的算法大概也很多吧,但是就为了练一手LCA+tarjin我就来做这题了,够裸了,还能验板子233。

这个算法主要是用到了并查集,找LCA,在找到询问对的时候存下LCA。然后最后利用公式结合tarjin得来的距离和LCA直接得出答案。

所以说此处我们进行遍历的目的有两个——1.找到目标点对的LCA,2.找到所有点距离初始点的距离。最后的答案是通过以上我们得到的信息算出来的。

该题详情请见代码。

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=4e4+5;
 4 typedef pair<int,int> PII;
 5 struct edge{
 6     int to,len;
 7 };
 8 struct askedge{
 9     int from,to,lca;
10 }ae[300];//询问对
11 int n,m;
12 vector<edge> G[N];//邻接表
13 vector<PII> pp[N];//存储每个点相对的询问点
14 int dist[N];//距离
15 int fa[N];//并查集
16 int Find(int x)
17 {
18     if(x==fa[x]) return x;
19     else return fa[x]=Find(fa[x]);
20 }
21 void Union(int x,int y)
22 {
23     x=Find(x);y=Find(y);
24     if(x!=y) fa[y]=x;
25 }
26 void dfs(int now)
27 {
28     fa[now]=now;//初始化,分离成init()函数也没问题
29     for(int i=0;i<pp[now].size();i++)//看当前这个点有没有它的点对已经被搜索到
30     {
31         PII &v=pp[now][i];
32         if(dist[v.first]!=-1){
33             ae[v.second].lca=fa[v.first];//如果存在,他们的lca就是当前点对象的爸爸
34         }
35     }
36     for(int i=0;i<G[now].size();i++)//遍历搜索
37     {
38         edge &v=G[now][i];
39         if(dist[v.to]==-1)
40         {
41             dist[v.to]=dist[now]+v.len;
42             dfs(v.to);
43             Union(now,v.to);//回溯时合并
44         }
45     }
46 }
47 int main()
48 {
49     int T;
50     scanf("%d",&T);
51     while(T--)
52     {
53         scanf("%d%d",&n,&m);
54         for(int i=0;i<=n;i++)//初始化
55         {
56             pp[i].clear();
57             G[i].clear();
58         }
59         for(int i=0;i<=m;i++)
60             pp[i].clear();
61         for(int i=0,u,v,len;i<n-1;i++)//读入图
62         {
63             scanf("%d%d%d",&u,&v,&len);
64             G[u].push_back(edge {v,len});
65             G[v].push_back(edge {u,len});
66         }
67         for(int i=1;i<=m;i++)//读入询问
68         {
69             int u,v;
70             scanf("%d%d",&u,&v);
71             pp[u].push_back(make_pair(v,i));
72             pp[v].push_back(make_pair(u,i));
73             ae[i]={u,v,-1};
74         }
75         memset(dist,-1,sizeof(dist));
76         dist[1]=0;
77         dfs(1);//开始tarjin
78         for(int i=1;i<=m;i++)//对每次询问输出答案
79         {
80             askedge &u=ae[i];
81             printf("%d
",dist[u.from]+dist[u.to]-2*dist[u.lca]);//公式
82         }
83     }
84     return 0;
85 }
原文地址:https://www.cnblogs.com/computer-luo/p/9622227.html