HDU 2586 How far away ?(LCA在线算法实现)

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

题意:
给出一棵树,求出树上任意两点之间的距离。

思路:

这道题可以利用LCA来做,记录好每个点距离根结点的距离,然后只要计算出两点的LCA,这样一来答案就是distance[u]+distance[v]-2distance[LCA]。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<sstream>
  6 #include<vector>
  7 #include<stack>
  8 #include<queue>
  9 #include<cmath>
 10 #include<map>
 11 #include<set>
 12 using namespace std;
 13 typedef long long ll;
 14 typedef pair<int,ll> pll;
 15 const int INF = 0x3f3f3f3f;
 16 const int maxn=40000+5;
 17
 18 int n, m;
 19 int num;
 20 int tot;
 21 int head[maxn];
 22 int vis[maxn];
 23 int ver[2*maxn];
 24 int deep[2*maxn];
 25 int dir[maxn];
 26 int first[maxn];
 27 int dp[2*maxn][25];
 28
 29 struct node
 30 {
 31     int v,w;
 32     int next;
 33 }e[2*maxn];
 34
 35 void addEdge(int u, int v, int w)
 36 {
 37     e[num].v=v;
 38     e[num].w=w;
 39     e[num].next=head[u];
 40     head[u]=num++;
 41 }
 42
 43 void dfs(int u, int dep)
 44 {
 45     vis[u]=1;
 46     ver[++tot]=u;   //遍历序列
 47     first[u]=tot;   //结点第一次出现位置
 48     deep[tot]=dep;     //深度
 49     for(int i=head[u];i!=-1;i=e[i].next)
 50     {
 51         if(!vis[e[i].v])
 52         {
 53             int v=e[i].v, w=e[i].w;
 54             dir[v]=dir[u]+w;   //距离
 55             dfs(v,dep+1);
 56             ver[++tot]=u;      //回溯
 57             deep[tot]=dep;
 58         }
 59     }
 60 }
 61
 62 void ST(int n)
 63 {
 64     for(int i=1;i<=n;i++)  dp[i][0]=i;
 65     for(int j=1;(1<<j)<=n;j++)
 66         for(int i=1;i+(1<<j)-1<=n;i++)
 67         {
 68             int a=dp[i][j-1],b=dp[i+(1<<(j-1))][j-1];
 69             dp[i][j]=deep[a]<deep[b]?a:b;
 70         }
 71 }
 72
 73 int RMQ(int L, int R)
 74 {
 75     int k=0;
 76     while((1<<(k+1))<=R-L+1)  k++;
 77     int a=dp[L][k], b=dp[R-(1<<k)+1][k];
 78     return deep[a]<deep[b]?a:b;
 79 }
 80
 81 int LCA(int u, int v)
 82 {
 83     int x=first[u], y=first[v];   //查找出他最先出现的地方
 84     if(x>y)  swap(x,y);
 85     int res=RMQ(x,y);    //查询出的是他祖先的下标
 86     return ver[res];
 87 }
 88
 89 int main()
 90 {
 91     //freopen("in.txt","r",stdin);
 92     int T;
 93     scanf("%d",&T);
 94     while(T--)
 95     {
 96         num=0; tot=0;
 97         memset(head,-1,sizeof(head));
 98         memset(vis,0,sizeof(vis));
 99         scanf("%d%d",&n,&m);
100         for(int i=1;i<n;i++)
101         {
102             int u,v,w;
103             scanf("%d%d%d",&u,&v,&w);
104             addEdge(u,v,w);
105             addEdge(v,u,w);
106         }
107         dir[1]=0;
108         dfs(1,1);
109         ST(2*n-1);
110         while(m--)
111         {
112             int u,v;
113             scanf("%d%d",&u,&v);
114             int lca=LCA(u,v);
115             printf("%d\n",dir[u]+dir[v]-2*dir[lca]);
116         }
117     }
118     return 0;
119 }
时间: 2024-10-10 09:27:17

HDU 2586 How far away ?(LCA在线算法实现)的相关文章

hihocoder1069最近公共祖先&#183;三(LCA在线算法--DFS+RMQ-ST)

树上任意两点的最近祖先,必定就是这两个节点的最短路径上深度最小的那个点. 例如:下图中,节点7和5,其最短路径为7--4--1--5, 这条路径上深度最小的点为节点1,其深度为1.节点1即为节点7和5的LCA. 因此,要找到任意两个节点的LCA,只需要先找到上述最短路径,再找到最短路径中深度最小的点.而这下面所述LCA在线算法所做的事. LCA在线算法描述(以上图为例): 1.获得“最短路径”(并不是真正的一条路径,包含其他节点,但不影响算法的正确性) 采用DFS遍历整棵树,得到以下数据: (1

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

LCA在线算法详解

LCA(最近公共祖先)的求法有多种,这里先介绍第一种:在线算法. 声明一下:下面的内容参考了http://www.cnblogs.com/scau20110726/archive/2013/05/26/3100812.html. 在线算法就是利用了DFS和RMQ两种算法,它先是预处理好所有情况,然后根据输入输出答案,在输入比较多的时候用比较好. 上面两张图介绍了在线算法的做法,要理解并不难,下面附上实现代码: 1 /******************************* 2 dfs实现代

HDU 2586 How far away? Tarjan算法 并查集 LCA

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 23506    Accepted Submission(s): 9329 Problem Description There are n houses in the village and some bidirectional roads connecting them. Every da

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 在线算法 zoj 3195

题目链接:Design the city 题目大意是对给定3点,求这三个点只之间的最短距离.三个点两两组合求lca:dis[u]+dis[v]-dis[lca];将三个组合值相加除以2即为答案. RMQ算法学习:http://blog.csdn.net/liang5630/article/details/7917702 对于lca->RMQ的转化,可以参看巨巨写的ppt. 欧拉序列:euler[N]; 深度序列:depth[N]; #include <iostream> #include

hdu2874 LCA在线算法

Connections between cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 8857    Accepted Submission(s): 2151 Problem Description After World War X, a lot of cities have been seriously damag

LCA最近公共祖先 在线算法和离线算法 模板

原理讲解:http://dongxicheng.org/structure/lca-rmq/ 在线算法模板: /** LCA在线算法O(nlogn) 主函数调用: init(); tot=0,dir[1]=0; dfs(1,1); ST(2*n-1); int lca=LCA(u,v); */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #in

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