题目链接

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 by 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 are to 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个节点的树,每条边上有一个权值代表这两个点之间的距离,现在m次询问:从节点a到节点b的路径长?

思路:预处理所有节点到根节点(定为节点1)的距离,以及所有节点的祖先信息(fa[i][j]表示节点 i 向上距离为 (1<<j)的祖先节点编号),计算a和b到根节点的距离和,减去两倍的最近公共祖先的到根节点的距离值。

代码如下:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 4e4 + ; int head[N], cnt;
struct Edge
{
int to, next;
int value;
}e[ * N]; struct Node {
int fa[];
int deep;
int sum;
bool state;
}node[N]; void insert(int u, int v, int value)
{
e[++cnt].to = v;
e[cnt].next = head[u];
e[cnt].value = value;
head[u] = cnt;
e[++cnt].to = u;
e[cnt].next = head[v];
e[cnt].value = value;
head[v] = cnt;
}
int cal(int x, int t)
{
for (int i = ; i <= ; i++)
if (t&( << i)) x = node[x].fa[i];
return x;
}
void dfs(int x)
{
node[x].state = ;
for (int i = ; i <= ; i++)
{
if (node[x].deep<( << i))break;
node[x].fa[i] = node[node[x].fa[i - ]].fa[i-];///倍增处理祖先信息
}
for (int i = head[x]; i; i = e[i].next)
{
if (node[e[i].to].state) continue;
node[e[i].to].deep = node[x].deep+ ;
node[e[i].to].fa[] = x;
node[e[i].to].sum = node[x].sum+e[i].value;
dfs(e[i].to);
}
}
int lca(int x, int y)///求lca
{
if (node[x].deep<node[y].deep) swap(x, y);
x = cal(x, node[x].deep - node[y].deep);
for (int i = ; i >= ; i--)
if (node[x].fa[i] != node[y].fa[i])
{
x = node[x].fa[i];
y = node[y].fa[i];
}
if (x == y)return x;
else return node[x].fa[];
} void init()
{
cnt = ;
memset(head, , sizeof(head));
memset(node, , sizeof(node));
} int main()
{
int T; cin >> T;
while (T--)
{
init();
int n, m; cin >> n >> m;
for (int i = ; i < n-; i++) {
int x, y, v; scanf("%d%d%d",&x,&y,&v);
insert(x,y,v);
}
dfs();
for (int i = ; i < m; i++) {
int x, y; scanf("%d%d",&x,&y);
int pa = lca(x, y);
int ans = node[x].sum - node[pa].sum + node[y].sum - node[pa].sum;
cout << ans << endl;
}
}
return ;
}

LCA最近公共祖先-- HDU 2586的更多相关文章

  1. lca 最近公共祖先

    http://poj.org/problem?id=1330 #include<cstdio> #include<cstring> #include<algorithm& ...

  2. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)

    Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...

  3. LCA(最近公共祖先)模板

    Tarjan版本 /* gyt Live up to every day */ #pragma comment(linker,"/STACK:1024000000,1024000000&qu ...

  4. CodeVs.1036 商务旅行 ( LCA 最近公共祖先 )

    CodeVs.1036 商务旅行 ( LCA 最近公共祖先 ) 题意分析 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从 ...

  5. LCA近期公共祖先

    LCA近期公共祖先 该分析转之:http://kmplayer.iteye.com/blog/604518 1,并查集+dfs 对整个树进行深度优先遍历.并在遍历的过程中不断地把一些眼下可能查询到的而 ...

  6. LCA 近期公共祖先 小结

    LCA 近期公共祖先 小结 以poj 1330为例.对LCA的3种经常使用的算法进行介绍,分别为 1. 离线tarjan 2. 基于倍增法的LCA 3. 基于RMQ的LCA 1. 离线tarjan / ...

  7. HDU 4547 CD操作 (LCA最近公共祖先Tarjan模版)

    CD操作 倍增法  https://i.cnblogs.com/EditPosts.aspx?postid=8605845 Time Limit : 10000/5000ms (Java/Other) ...

  8. D5 LCA 最近公共祖先

    第一题: POJ 1330 Nearest Common Ancestors POJ 1330 这个题可不是以1为根节点,不看题就会一直wa呀: 加一个找根节点的措施: #include<alg ...

  9. LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现

    首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵 ...

随机推荐

  1. c 和 c++ 啊 Make

  2. selenium添加chrome配置项

    selenium虽然强大,但也有不方便的地方,selenium每次启动浏览器都是一个全新的浏览器,并没有加载任何的配置,这样在爬取一些需要登陆才能看到的页面时就有些不太方便.但我们可以通过加载chro ...

  3. HTML简介 页面标记

    HTML简介 HTML 1.0 : 1993年 HTML 2.0 : 1995年 HTML 3.2 : 1997年 HTML 4.01 : 1999年 HTML  5 : 2008年 XML:可扩展标 ...

  4. day56_9_20orm中的关键字段,orm查询13方法整合,查询优化和事务。

    一.常用字段. 在orm中有一些字段是常用字段: 1.AutoField 这个字段是自增的,必须填入参数primary_key=True,也就是说这个字段是表的主键,如果表类中没有自增列,就会自动创建 ...

  5. Dockerfil

    Dockerfile简介 dockerfile 是一个文本格式的配置文件, 用户可以使用 Dockerfile 来快速创建自定义的镜像,另外,使用Dockerfile去构建镜像好比使用pom去构建ma ...

  6. Go micro 入门

    路由跳转 官方文档 本质上是选择不同的方式将HTTP信息合理的转发至后端处理,而不同的方式相当于不同请求的接收器,接收后再将其转发至不同的后端服务,完成整个请求的调用. micro 将请求选择不同的方 ...

  7. 【2019.7.20 NOIP模拟赛 T2】B(B)(数位DP)

    数位\(DP\) 首先考虑二进制数\(G(i)\)的一些性质: \(G(i)\)不可能有连续两位第\(x\)位和第\(x+1\)位都是\(1\).因为这样就可以进位到第\(x+2\)位.其余情况下,这 ...

  8. [LOJ 6213]「美团 CodeM 决赛」radar

    [LOJ 6213]「美团 CodeM 决赛」radar 题意 给定 \(n\) 个横坐标 \(x_i\) , 为它们选择一个不超过 \(y_i\) 的纵坐标 \(h_i\), 产生 \(c_ih_i ...

  9. vscode配置编译运行调试C/C++文件-windows环境

    在windows环境下,编译运行小文件的C/C++环境 软件准备: vscode mingw64(官网下特别慢,可以在devc++安装软件里中找,放到全局变量中) 插件下载: Run Code C/C ...

  10. Sencha Modern

    Sencha Modern  前言         经过一个月捣鼓,基于sencha公司最新框架版本 ExtJS7.0 modern 的示例代码可以和大家见面了.示例中对系统主题.公共(组件,方法)封 ...