[SPOJ913]QTREE2 - Query on a tree II【倍增LCA】
题目描述
题目大意
给一棵树,有两种操作:
- 求(u,v)路径的距离。
- 求以u为起点,v为终点的第k的节点.
分析
比较简单的倍增LCA模板题。
首先对于第一问,我们只需要预处理出根节点到各个节点之间的距离,然后倍增LCA求解就可以了。
那么第二问我WA了6发,原来是眼瞎和手残打错了两个字符错掉了。
我们将问题分成3个部分:
- LCA是第k个
- 第k个在u到LCA的路径上
- 第k个在LCA到v的路径上。
首先如果LCA是第k个,那么直接输出。
如果是第二种情况,那么从u开始做倍增,每一次k-(1<<i)就可以了。
小细节:只能将k变成1,模拟可证明。
第三种情况,那么我们的答案就是从v的第(dep[u]+dep[v]-2*dep[lca]+2),模拟可得该式。
ac代码
#include <bits/stdc++.h>
#define ll long long
#define ms(a, b) memset(a, b, sizeof(a))
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
template <typename T>
inline void read(T &x) {
x = 0; T fl = 1;
char ch = 0;
while (ch < '0' || ch > '9') {
if (ch == '-') fl = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
x *= fl;
}
#define N 20005
struct edge {
int to, nt;
ll w;
}E[N << 1];
ll dis[N];
int f[N][31], H[N], dep[N];
int cnt, n;
void add_edge(int u, int v, ll w) {
E[++ cnt] = (edge){v, H[u], w};
H[u] = cnt;
}
void dfs(int u, int fa, int dist) {
f[u][0] = fa;
dis[u] = dist;
for (int i = 1; i <= 30; i ++)
f[u][i] = f[f[u][i - 1]][i - 1];
for (int e = H[u]; e; e = E[e].nt) {
int v = E[e].to;
if (v == fa) continue;
dep[v] = dep[u] + 1;
dfs(v, u, dist + E[e].w);
}
}
int lca(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
for (int i = 30; i >= 0; i --)
if (dep[v] <= dep[f[u][i]]) u = f[u][i];
if (u == v) return u;
for (int i = 30; i >= 0; i --)
if (f[u][i] != f[v][i]) {
u = f[u][i];
v = f[v][i];
}
return f[u][0];
}
int solve(int u, int v, int k) {
int Lca = lca(u, v);
if (dep[u] - dep[Lca] + 1 == k) return Lca;
else {
if (dep[u] - dep[Lca] + 1 > k) {
for (int i = 30; i >= 0; i --)
if (k - 1 >= (1 << i)) k -= (1 << i), u = f[u][i];
return u;
}
else {
k = dep[u] + dep[v]- dep[Lca] * 2 - k + 2;
for (int i = 30; i >= 0; i --)
if (k - 1 >= (1 << i)) k -= (1 << i), v = f[v][i];
return v;
}
}
}
int main() {
int cas;
read(cas);
char opt[10];
while (cas --) {
cnt = 0;
ms(H, 0);
ms(dis, 0);
ms(dep, 0);
ms(f, 0);
read(n);
for (int i = 1; i < n; i ++) {
int u, v; ll w;
read(u); read(v); read(w);
add_edge(u, v, w);
add_edge(v, u, w);
}
dep[1] = 1;
dfs(1, 0, 0);
while (1) {
scanf("%s", opt);
if (opt[1] == 'O') break;
if (opt[0] == 'D') {
int u, v;
read(u); read(v);
int Lca = lca(u, v), res;
printf("%lld\n", dis[u] + dis[v] - dis[Lca] * 2);
}
else {
int u, v, k;
read(u); read(v); read(k);
printf("%d\n", solve(u, v, k));
}
}
}
return 0;
}
[SPOJ913]QTREE2 - Query on a tree II【倍增LCA】的更多相关文章
- spoj 913 Query on a tree II (倍增lca)
Query on a tree II You are given a tree (an undirected acyclic connected graph) with N nodes, and ed ...
- 【SPOJ QTREE2】QTREE2 - Query on a tree II(LCA)
You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, ...
- Query on a tree II 倍增LCA
You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, ...
- LCA SP913 QTREE2 - Query on a tree II
SP913 QTREE2 - Query on a tree II 给定一棵n个点的树,边具有边权.要求作以下操作: DIST a b 询问点a至点b路径上的边权之和 KTH a b k 询问点a至点 ...
- SP913 QTREE2 - Query on a tree II
思路 第一个可以倍增,第二个讨论在a到lca的路径上还是lca到b的路径上, 倍增即可 代码 #include <cstdio> #include <algorithm> #i ...
- SPOJ QTREE2 Query on a tree II
传送门 倍增水题…… 本来还想用LCT做的……然后发现根本不需要 //minamoto #include<bits/stdc++.h> using namespace std; #defi ...
- SPOJ COT2 - Count on a tree II(LCA+离散化+树上莫队)
COT2 - Count on a tree II #tree You are given a tree with N nodes. The tree nodes are numbered from ...
- QTREE2 spoj 913. Query on a tree II 经典的倍增思想
QTREE2 经典的倍增思想 题目: 给出一棵树,求: 1.两点之间距离. 2.从节点x到节点y最短路径上第k个节点的编号. 分析: 第一问的话,随便以一个节点为根,求得其他节点到根的距离,然后对于每 ...
- SPOJ913 Query on a tree II
Time Limit: 433MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Description You are g ...
随机推荐
- 软件工程(FZU2015) 赛季得分榜,第六回合
SE_FZU目录:1 2 3 4 5 6 7 8 9 10 11 12 13 积分规则 积分制: 作业为10分制,练习为3分制:alpha30分: 团队项目分=团队得分+个人贡献分 个人贡献分: 个人 ...
- 【学习总结】GirlsInAI ML-diary day-3-数据类型
[学习总结]GirlsInAI ML-diary 总 原博github链接-day3 数据类型 熟悉一下计算时可能碰到的数据类型.(计算时...) 1-打开jupyter,new一个新python文件 ...
- Linux系统tree工具
当用户在linux平台中需要需要查看一个非当前目录的目录下有哪些文件和子文件时,最普通的办法就是cd该目录,然后再ls,这个操作令人不舒适,因为查看完以后,用户还需要切换到原来的目录.现在介绍一款非常 ...
- PHP开发编码规范
(转载:https://blog.csdn.net/alexdream/article/details/2213313) 这些年来多从事Linux下PHP和C相关的开发,带过很多项目和团队,下面是根据 ...
- Postman的Post请求方式的四种类型的数据
1. form-data 就是http请求中的multipart/form-data,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开.既可以上传键值对,也可以上传文件.当上传的字段是文件时 ...
- [转帖]HTTP 头部解释
HTTP 头部解释 https://www.cnblogs.com/poissonnotes/p/4844014.html 之前看的太粗了 同事闻起来 referer 才知道自己所知甚少.. ==== ...
- 工程下CmakeLists.txt
2.工程下Cmake 本小节的任务是让上一小结的程序更像一个工程: 为工程添加一个子目录 src,用来放置工程源代码 : 添加一个子目录doc,用来放置这个工程的文档 hello.txt: 在工程目录 ...
- Ajax发送请求等待时弹出模态框等待提示
主要的代码分为两块,一个是CSS定义模态框,另一个是在Ajax中弹出模态框. 查看菜鸟教程中的模态框教程demo,http://www.runoob.com/try/try.php?filename= ...
- 剑指offer(20)二叉搜索树与双向表
题目: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路一:递归法 1.将左子树构造成双链表,并返回链表头节点. 2.定位至左子 ...
- git简介及安装(win10)
一句话介绍git Git是Linus Torvalds编写,目前是世界上最先进的分布式版本控制系统. git能干什么? 代码备份.还原,版本管理,分支管理,解决冲突,协同开发... 安装git > ...