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. linux进程的管道通信

    linux进程的管道通信 要求 编程实现进程的管道通信,掌握管道通信的同步和互斥机制. 相关函数 pipe管道 指用于连接一个读进程和一个写进程以实现他们之间通信的一个共享文件,又名pipe文件.向管 ...

  2. CSS鼠标手势大全

    实例: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3. ...

  3. java Web 过滤器Filter详解

    简介 Filter也称之为过滤器,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊 ...

  4. SQL中对数据截取替换

    REPLACE(要修改字段名,‘被替换的特定字符’,‘替换的字符’) 表结构和插入数据 CREATE DATABASE TEST GO USE TEST GO CREATE TABLE TestTab ...

  5. 中国大学MOOC 玩转AutoCAD 熟悉AutoCAD的人机交互方式

  6. solr第一天 基础增删改查操作

    全文检索技术   Lucene&Solr               Part2 1 课程计划 1.索引库的维护 a) 添加文档 b) 删除文档 c) 修改文档 2.Lucene的查询 a)  ...

  7. 70个HR面试题

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

  8. jquery extend 多个扩展方法

    $.fn.extend({ SetDict: function (option) { var txtControl = $(this); if (!txtControl.hasClass(" ...

  9. SQL 左联接去除左边重复的数据

    代码如下: use DB go select table1.*,b.OPTime from [dbo].[table1] left join( select * from (select table2 ...

  10. 验证码测试-demo

    <!DOCTYPE html><html><head><meta charset="UTF-8"><title>Inse ...