hdu 2586 How far away ?(离线求最近公共祖先)

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<vector>
  6 #include<cmath>
  7 #include<map>
  8 using namespace std;
  9
 10 const int mx=4e4+4;
 11 struct N
 12 {
 13     int v,d;
 14     N(int x,int y)
 15     {
 16         v=x;
 17         d=y;
 18     }
 19 };
 20 vector<N>g[mx],q[mx];
 21 int father[mx];
 22 int dis[mx];
 23 bool vs[mx];
 24 int ans[mx];
 25
 26 void Init(int n)
 27 {
 28     for (int i=1;i<=n;i++)
 29     {
 30         father[i]=i;
 31         dis[i]=0;
 32         vs[i]=false;
 33         g[i].clear();
 34         q[i].clear();
 35     }
 36 }
 37
 38 int Find(int x)
 39 {
 40     int w=x;
 41     while (w!=father[w]) w=father[w];
 42     while (x!=father[x])
 43     {
 44         int fa=father[x];
 45         father[x]=w;
 46         x=fa;
 47     }
 48     return w;
 49 }
 50
 51 void un(int x,int y)
 52 {
 53     int rx=Find(x);
 54     int ry=Find(y);
 55     father[y]=x;
 56 }
 57
 58 void dfs(int u,int fa,int d)
 59 {
 60     dis[u]=d;
 61     vs[u]=true;
 62     for (int i=0;i<g[u].size();i++)
 63     {
 64         N k=g[u][i];
 65         if (vs[k.v]) continue;
 66         dfs(k.v,u,d+k.d);
 67     }
 68     for (int i=0;i<q[u].size();i++)
 69     {
 70         N k=q[u][i];
 71         if (!vs[k.v]) continue;
 72         ans[k.d]=dis[u]+dis[k.v]-2*dis[Find(k.v)];
 73     }
 74     un(fa,u);
 75 }
 76
 77 int main()
 78 {
 79     int n,m;
 80     int t;
 81     scanf("%d",&t);
 82     while (t--)
 83     {
 84         scanf("%d%d",&n,&m);
 85         Init(n);
 86         for (int i=1;i<n;i++)
 87         {
 88             int u,v,w;
 89             scanf("%d%d%d",&u,&v,&w);
 90             g[u].push_back(N(v,w));
 91             g[v].push_back(N(u,w));
 92         }
 93         for (int i=1;i<=m;i++)
 94         {
 95             int u,v;
 96             scanf("%d%d",&u,&v);
 97             q[u].push_back(N(v,i));
 98             q[v].push_back(N(u,i));
 99         }
100         dfs(1,0,0);
101         for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
102     }
103 }
时间: 2024-07-28 17:52:57

hdu 2586 How far away ?(离线求最近公共祖先)的相关文章

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

题目地址:HDU 2586 LCA第一发. 纯模板题. 偷懒用的vector,结果一直爆栈.把G++改成C++就过了.. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <se

【LCA求最近公共祖先+vector构图】Distance Queries

Distance Queries 时间限制: 1 Sec  内存限制: 128 MB 题目描述 约翰的奶牛们拒绝跑他的马拉松,因为她们悠闲的生活不能承受他选择的长长的赛道.因此他决心找一条更合理的赛道.此题的输入于第一题相同,紧接着下一行输入一个整数K,以后K行为K个"距离问题".每个距离问题包括两个整数,就是约翰感兴趣的两个农场的编号,请你尽快算出这两地之间的距离. N个点,N-1条边 输入 第1行:两个分开的整数:N和M: 第2..M+1行:每行包括4个分开的内容,F1,F2,L,

求最近公共祖先(LCA)板子 x

LCA目前比较流行的算法主要有tarjian,倍增和树链剖分 1)tarjian 是一种离线算法,需要提前知道所有询问对 算法如下 1.读入所有询问对(u,v),并建好树(建议邻接表) 2.初始化每个节点各属一个并查集,都指向自己 3.对整棵树进行dfs(深度优先搜索)遍历 每处理到一个新节点(u)时看他的另一半(询问对象v)是否visit过,如果visit过了,则这组询问对的lca即v的并查集的根节点,若没有visit过,则继续向下深搜,该节点记为已visit 每当回溯的时候都将子节点的并查集

LCA 在线倍增法 求最近公共祖先

第一步:建树  这个就不说了 第二部:分为两步  分别是深度预处理和祖先DP预处理 DP预处理: int i,j; for(j=1;(1<<j)<n;j++) for(int i=0;i<n;++i) if(fa[i][j]=-1) fa[i][j]=fa[fa[i][j-1]][j-1];/*DP处理出i的2^j祖先是谁*/ 深度预处理: 1 void dfs(int now,int from,int deepth) 2 { 3 deep[now]=deepth; 4 for(i

用“倍增法”求最近公共祖先(LCA)

1.最近公共祖先:对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大.2.朴素算法:记录下每个节点的父亲,使节点u,v一步一步地向上找父亲,直到找到相同的“祖先”,即 是所求的答案,时间复杂度O(n).3.优化算法(倍增法):利用二进制的思想,想办法使一步一步向上搜变成以2^k地向上跳. 所以定义一个P[][]数组,使p[i][j]表示节点i的2^j倍祖先,因此p[i][0]即为i的父亲. 我们可以得到一个递推式p[i][j]=p

tarjan算法求最近公共祖先

tarjian算法 LCA: LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点.也就是说,在两个点通往根的道路上,肯定会有公共的节点,我们就是要求找到公共的节点中,深度尽量深的点.还可以表示成另一种说法,就是如果把树看成是一个图,这找到这两个点中的最短距离. LCA算法有在线算法也有离线算法,所谓的在线算法就是实时性的,而离线算法则是要求一次性读入所有的请求,然后在统一得处理.而在处理的过程中不一定是按照请求的输入顺序来处理的.说不定

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): 10312    Accepted Submission(s): 3743 Problem Description There are n houses in the village and some bidirectional roads connecting

HDU 2586 How far away?(LCA使用详解)

关键词:LCA.并查集.动态规划.深度优先搜索.哈希.RMQ.递归 题目: 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 ha

LCA(最近公共祖先)——离线 Tarjan 算法

一.梳理概念 定义:对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 通俗地讲,最近公共祖先节点,就是两个节点在这棵树上深度最大的公共的祖先节点,即两个点在这棵树上距离最近的公共祖先节点. 提示:父亲节点也是祖先节点,节点本身也是它的祖先节点. 给出一棵树,如图所示: 由上面的定义可知:3和5的最近公共祖先为1,5和6的最近公共祖先为2,2和7的最近公共祖先为2, 6和7的最近公共祖先为4. 二.繁文缛节 注意注意注意!!!尚