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). ttest 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 ab 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 思路:
倍增裸题。。。套板子,
求第k个的时候需要处理下,其他没什么。,。
实现代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int M = 2e5+;
int dist[M],p[M][],dep[M],head[M];
int cnt1,n; struct node{
int to,next,w;
}e[M]; void add(int u,int v,int w){
e[++cnt1].w=w;e[cnt1].to=v;e[cnt1].next=head[u];head[u]=cnt1;
e[++cnt1].w=w;e[cnt1].to=u;e[cnt1].next=head[v];head[v]=cnt1;
} void dfs(int u){
for(int i = head[u];i != -;i=e[i].next){
int v = e[i].to;
if(v == p[u][]) continue;
dep[v] = dep[u] + ;
dist[v] = dist[u] + e[i].w;
p[v][] = u; //p[i][0]存i的父节点
dfs(v);
}
} void init(){
for(int j = ;(<<j)<=n;j++){
for(int i = ;i <= n;i++){
p[i][j] = p[p[i][j-]][j-];
//cout<<i<<" "<<j<<" "<< p[i][j]<<endl;
}
}
} int lca(int a,int b){
if(dep[a] > dep[b]) swap(a,b);
int h = dep[b] - dep[a]; //h为高度差
for(int i = ;(<<i)<=h;i++){ //(1<<i)&f找到h化为2进制后1的位置,移动到相应的位置
if((<<i)&h) b = p[b][i];
//比如h = 5(101),先移动2^0祖先,然后再移动2^2祖先
}
//cout<<a<<" "<<b<<endl;
if(a!=b){
for(int i = ;i >= ;i --){
if(p[a][i]!=p[b][i]){ //从最大祖先开始,判断a,b祖先,是否相同
a = p[a][i]; b = p[b][i]; //如不相同,a,b,同时向上移动2^j
}
}
a = p[a][]; //这时a的father就是LCA
}
return a;
} int kth(int u,int k){
for(int i = ;i < ;i ++)
if(k >> i&)
u = p[u][i];
return u;
} int main()
{
int t,u,v,w,k;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
cnt1 = ;
//init();
memset(head,-,sizeof(head));
for(int i = ;i < n-;i ++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
dfs();
init();
char s[];
while(scanf("%s",s)!=EOF){
if(s[]=='O') break;
scanf("%d%d",&u,&v);
int num = lca(u,v);
if(s[]=='I'){
printf("%d\n",dist[u]+dist[v]-*dist[num]);
}
if(s[]=='T'){
scanf("%d",&k);
int x = dep[u] - dep[num];
if(x + >= k)
printf("%d\n",kth(u,k-));
else printf("%d\n",kth(v,dep[v]+dep[u]-*dep[num]+-k));
}
}
}
return ;
}

SPOJ QTREE2 (LCA - 倍增 在线)的更多相关文章

  1. LCA(倍增在线算法) codevs 2370 小机房的树

    codevs 2370 小机房的树 时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点, ...

  2. SPOJ DISQUERY LCA + 倍增

    裸题,如此之水- Code: #include<cstdio> #include<algorithm> using namespace std; const int maxn ...

  3. POJ - 1330 Nearest Common Ancestors(dfs+ST在线算法|LCA倍增法)

    1.输入树中的节点数N,输入树中的N-1条边.最后输入2个点,输出它们的最近公共祖先. 2.裸的最近公共祖先. 3. dfs+ST在线算法: /* LCA(POJ 1330) 在线算法 DFS+ST ...

  4. 【LCA倍增】POJ1330-Nearest Common Ancestors

    [知识点:离线算法&在线算法] 一个离线算法,在开始时就需要知道问题的所有输入数据,而且在解决一个问题后就要立即输出结果. 一个在线算法是指它可以以序列化的方式一个个的处理输入,也就是说在开始 ...

  5. 【codevs2370】小机房的树 LCA 倍增

    2370 小机房的树  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0 ...

  6. LCA倍增算法

    LCA 算法是一个技巧性很强的算法. 十分感谢月老提供的模板. 这里我实现LCA是通过倍增,其实就是二进制优化. 任何一个数都可以有2的阶数实现 例如16可以由1 2 4 8组合得到 5可以由1 2 ...

  7. 洛谷 3379 最近公共祖先(LCA 倍增)

    洛谷 3379 最近公共祖先(LCA 倍增) 题意分析 裸的板子题,但是注意这题n上限50w,我用的边表,所以要开到100w才能过,一开始re了两发,发现这个问题了. 代码总览 #include &l ...

  8. CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先)

    CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先) 题意分析 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天, ...

  9. POJ.1986 Distance Queries ( LCA 倍增 )

    POJ.1986 Distance Queries ( LCA 倍增 ) 题意分析 给出一个N个点,M条边的信息(u,v,w),表示树上u-v有一条边,边权为w,接下来有k个询问,每个询问为(a,b) ...

随机推荐

  1. Unable to start a VM due to insufficient capacity

    今天cloudstack中的一个普通用户创建虚拟机时,总是报错:Unable to start a VM due to insufficient capacity ,看management and a ...

  2. shell编程的笔记

    关于历史命令 Shell相关 !! 是上一次执行的命令 !字符串  指执行最近一次以这个字符串开头的命令 !$ 取出上一条命令最后一个单词或命令 *匹配0个或多个字符         ?匹配一个字符 ...

  3. jQuery上传文件

    1.引入资源 <script src="/yami/backend/backres/js/jquery.min.js"></script> <scri ...

  4. qemu安装

    1 下载qemu wget http://wiki.qemu-project.org/download/qemu-2.4.1.tar.bz2 2 解压qemu tar -jxvf qemu-2.4.1 ...

  5. 【LeeCode88】Merge Sorted Array★

    1.题目描述: 2.解题思路: 题意:两个由整数构成的有序数组nums1和nums2,合并nums2到nums1,使之成为一个有序数组.注意,假设数组nums1有足够的空间存储nums1和nums2的 ...

  6. 20155308《网络对抗》Exp6 信息搜集与漏洞扫描

    20155308<网络对抗>Exp6 信息搜集与漏洞扫描 原理与实践说明 实践内容 本实践的目标是掌握信息搜集的最基础技能.具体有: 各种搜索技巧的应用 DNS IP注册信息的查询 基本的 ...

  7. # 2017-2018-2 20155319『网络对抗技术』Exp2:后门原理与实践

    2017-2018-2 20155319『网络对抗技术』Exp2:后门原理与实践 1.实验准备 一.实验说明 任务一:使用netcat获取主机操作Shell,cron启动 (0.5分) 任务二:使用s ...

  8. sql——sql中的各种连接

    现有两张表 tablea 和 tableb     各种连接 1.笛尔卡积 SELECT * FROM TabA a,TabB b where a.id = b.id /*笛尔卡积乘积*/ 返回的结果 ...

  9. phpmyadmin连接MySQL服务器被拒绝

    显示: phpMyAdmin 尝试连接到MySQL服务器,但服务器拒绝连接.您应该检查配置文件中的主机.用户名和密码,并确认这些信息与 MySQL 服务器管理员所给出的信息一致. 原因: 可能是修改了 ...

  10. Monkey稳定性测试

    1.环境准备:Android SDK环境配置 2.手机连接/模拟器连接 : 1)手机打开开发者模式并允许USB连接 2)校验手机是否连接:打开cmd 输入 adb devices 3.查找apk包名及 ...