You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. Each edge has an integer value assigned to it, representing its length.

We will ask you to perfrom some instructions of the following form:

  • DIST a b : ask for the distance between node a and node b
    or
  • KTH a b k : ask for the k-th node on the path from node a to node b

Example:
N = 6
1 2 1 // edge connects node 1 and node 2 has cost 1
2 4 1
2 5 2
1 3 1
3 6 2

Path from node 4 to node 6 is 4 -> 2 -> 1 -> 3 -> 6
DIST 4 6 : answer is 5 (1 + 1 + 1 + 2 = 5)
KTH 4 6 4 : answer is 3 (the 4-th node on the path from node 4 to node 6 is 3)

Input

The first line of input contains an integer t, the number of test cases (t <= 25). t test cases follow.

For each test case:

  • In the first line there is an integer N (N <= 10000)
  • In the next N-1 lines, the i-th line describes the i-th edge: a line with three integers a b c denotes an edge between a, b of cost c (c <= 100000)
  • The next lines contain instructions "DIST a b" or "KTH a b k"
  • The end of each test case is signified by the string "DONE".

There is one blank line between successive tests.

Output

For each "DIST" or "KTH" operation, write one integer representing its result.

Print one blank line after each test.

Example

Input:
1 6
1 2 1
2 4 1
2 5 2
1 3 1
3 6 2
DIST 4 6
KTH 4 6 4
DONE Output:
5
3

看到树上两点距离很容易想到LCA,
对于第K个点我们同样可以倍增解决;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<time.h>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#include<cctype>
//#pragma GCC optimize(2)
using namespace std;
#define maxn 200005
#define inf 0x7fffffff
//#define INF 1e18
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
#define rdult(x) scanf("%lu",&x)
#define rdlf(x) scanf("%lf",&x)
#define rdstr(x) scanf("%s",x)
#define mclr(x,a) memset((x),a,sizeof(x))
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 9999973;
#define Mod 1000000000
#define sq(x) (x)*(x)
#define eps 1e-5
typedef pair<int, int> pii;
#define pi acos(-1.0)
//const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef pair<int, int> pii; inline int rd() {
int x = 0;
char c = getchar();
bool f = false;
while (!isdigit(c)) {
if (c == '-') f = true;
c = getchar();
}
while (isdigit(c)) {
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return f ? -x : x;
} ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a%b);
}
int sqr(int x) { return x * x; } /*ll ans;
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) {
x = 1; y = 0; return a;
}
ans = exgcd(b, a%b, x, y);
ll t = x; x = y; y = t - a / b * y;
return ans;
}
*/ struct node {
int u, v, w, nxt;
}e[maxn];
int head[maxn];
int tot;
int n;
int dis[maxn], dep[maxn];
int fa[maxn][20];
void init() {
ms(e); ms(head); tot = 0; ms(dis); ms(dep);
ms(fa);
} void addedge(int u, int v, int w) {
e[++tot].u = u; e[tot].v = v; e[tot].nxt = head[u]; e[tot].w = w;
head[u] = tot;
} void dfs(int rt) {
for (int i = 1; i <= (int)log(n) / log(2) + 1; i++)
fa[rt][i] = fa[fa[rt][i - 1]][i - 1];
for (int i = head[rt]; i; i = e[i].nxt) {
int v = e[i].v;
if (v == fa[rt][0])continue;
fa[v][0] = rt; dep[v] = dep[rt] + 1;
dis[v] = dis[rt] + e[i].w;
dfs(v);
}
} int LCA(int x, int y) {
if (dep[x] > dep[y])swap(x, y);
for (int i = (int)log(n) / log(2) + 1; i >= 0; i--) {
if (dep[fa[y][i]] >= dep[x])y = fa[y][i];
}
if (x == y)return x;
for (int i = (int)log(n) / log(2) + 1; i >= 0; i--) {
if (fa[x][i] != fa[y][i]) {
x = fa[x][i]; y = fa[y][i];
}
}
return fa[x][0];
} int main()
{
// ios::sync_with_stdio(0);
int T = rd();
while (T--) {
n = rd();
init();
for (int i = 1; i < n; i++) {
int u = rd(), v = rd(), w = rd();
addedge(u, v, w); addedge(v, u, w);
}
dfs(1);
char op[20];
while (rdstr(op) != EOF && op[1] != 'O') {
if (op[1] == 'I') {
int u = rd(), v = rd();
// cout << dis[u] << ' ' << dis[v] << ' ' << dis[LCA(u, v)] << endl;
printf("%d\n", dis[u] + dis[v] - 2 * dis[LCA(u, v)]);
}
else {
int u = rd(), v = rd(), k = rd();
int root = LCA(u, v);
int ans;
if (dep[u] - dep[root] + 1 >= k) {
ans = dep[u] - k + 1;
int i;
for (i = 0; (1 << i) <= dep[u]; i++); i--;
for (int j = i; j >= 0; j--) {
if (dep[u] - (1 << j) >= ans)u = fa[u][j];
}
printf("%d\n", u);
}
else {
ans = dep[root] + k - (dep[u] - dep[root] + 1);
int i;
for (i = 0; (1 << i) <= dep[v]; i++); i--;
for (int j = i; j >= 0; j--) {
if (dep[v] - (1 << j) >= ans)v = fa[v][j];
}
printf("%d\n", v);
}
}
}
}
return 0;
}

Query on a tree II 倍增LCA的更多相关文章

  1. 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 ...

  2. 【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, ...

  3. 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至点 ...

  4. [SPOJ913]QTREE2 - Query on a tree II【倍增LCA】

    题目描述 [传送门] 题目大意 给一棵树,有两种操作: 求(u,v)路径的距离. 求以u为起点,v为终点的第k的节点. 分析 比较简单的倍增LCA模板题. 首先对于第一问,我们只需要预处理出根节点到各 ...

  5. 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  ...

  6. SPOJ Query on a tree II (树剖||倍增LCA)(占位)

    You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, ...

  7. LCA【SP913】Qtree - Query on a tree II

    Description 给定一棵n个点的树,边具有边权.要求作以下操作: DIST a b 询问点a至点b路径上的边权之和 KTH a b k 询问点a至点b有向路径上的第k个点的编号 有多组测试数据 ...

  8. QTREE2 spoj 913. Query on a tree II 经典的倍增思想

    QTREE2 经典的倍增思想 题目: 给出一棵树,求: 1.两点之间距离. 2.从节点x到节点y最短路径上第k个节点的编号. 分析: 第一问的话,随便以一个节点为根,求得其他节点到根的距离,然后对于每 ...

  9. SPOJ913 Query on a tree II

    Time Limit: 433MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description You are g ...

随机推荐

  1. CentOs登陆输入root作为用户名

  2. JanusGraph :Cassandra作为存储后端的情况下,JanusGraph的安装方法

    Cassandra作为存储后端的情况下,JanusGraph的安装方法 Cassandra作为存储后端的情况下,JanusGraph的安装分为四种方式. 分别是: 1.本地服务器模式(这里的服务器指的 ...

  3. Linux下查看进程的命令输出的内容解释

    Linux下查看进程的命令输出的内容解释 ps (process status) ps -e 或者ps -A (-e和-A完全一样) PID           TTY         TIME   ...

  4. codeforce468DIV2——D. Peculiar apple-tree

    题意给你一颗树,开始时每个结点都有一个小球,每一秒钟每个小球都往上滚一层,当两个球在同一个结点的时候会被消去,如果三个五个七个等在同一个结点的化消去后只剩一个. 分析 这对我来说就TM是英语阅读理解哇 ...

  5. 下载Redis

    1.下载当前Redis 官网:https://redis.io/ 当前稳定版本是4.0.11,如下图,点Download it下面的链接进行下载 2.下载历史版本的Resis 网址: http://d ...

  6. 70个HR面试题

    请你自我介绍一下你自己,      回答提示:一般人回答这个问题过于平常,只说姓名.年龄.爱好.工作经验,这些在简历上都有,其实,企业最希望知道的是求职者能否胜任工作,包括:最强的技能.最深入研究的知 ...

  7. win32多线程(三) 死锁

    任何时候当一段代码需要两个(或更多)资源时,都有潜在性的死锁. void SwapLists(List *list1, List *list2) { List *tmp_list; EnterCrit ...

  8. nodelet的理解

    1.介绍 nodelet包可以为在相同进程中的多个算法之间实现零拷贝的传输方式. 这个包也提供了实现一个nodelet所需的nodelet基类以及用于实例化nodelet的NodeletLoader类 ...

  9. Part3_lesson3---ARM伪指令学习

    1.ARM机器码 对elf格式的文件进行反汇编可得到相应汇编文件的机器码: arm-linux-objdump -D -S start.elf 机器码的解析,可以参考文件ARM Architectur ...

  10. openvswitch安装

    安装前准备软件包及版本 Gcc pkg-config autoconf automake m4 python2.X 下载OVS软件包 http://openvswitch.org/releases/o ...