题目链接【http://www.spoj.com/problems/QTREE/】

题意:给出一个包含N(N<=10000)节点的无根树,有多次询问,询问的方式有两种1、DIST  a b 求a->b之间的距离。2、KTH a b k 求a->b链上的第k个节点是谁,。如果输入DONE,结束询问。

思路:首先想到用倍增法可以解决第一种询问,只需要在DFS时候维护一个dis[i](表示i节点到根节点之间的距离,因为是无根树,我们定义节点1为根),dis(a->b)=dis[a]+dis[b]-dia[lca(a,b)]。第二种询问的解法是首先求出a,b的lca,然后根据lca到a到b的深度判断第k个数在左半枝还是右半枝(可以定义lca为左半枝),然后用倍增的方法求出第k个节点。

#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = ;
struct node
{
int id, len, next;
} E[maxn << ];
int p[maxn << ], num;
void init()
{
memset(p, -, sizeof(p));
num = ;
}
void add(int u, int v, int dis)
{
E[num].id = u;
E[num].len = dis;
E[num].next = p[v];
p[v] = num++;
}
//------------------------------------------邻接表
int T, N;
int fa[][maxn];//倍增数组
int dis[maxn], dep[maxn];//距离,深度数组
void DFS(int u, int FA)//DFS求出每个节点的深度,每个节点到根节点的距离,和每个节点跳1步到达的位置
{
for(int l = p[u]; l != -; l = E[l].next)
{
int id = E[l].id;
if(id == FA) continue;
fa[][id] = u;
dep[id] = dep[u] + ;
dis[id] = dis[u] + E[l].len;
DFS(id, u);
}
}
void INIT()//初始化倍增数组
{
memset(fa, -, sizeof(fa));
memset(dis, , sizeof(dis));
memset(dep, , sizeof(dep));
DFS(, -);
for(int k = ; k + <= ; k++)
{
for(int u = ; u <= N; u++)
{
if(fa[k][u] < )
fa[k + ][u] = -;
else
fa[k + ][u] = fa[k][fa[k][u]];
}
}
}
int LCA(int u, int v)
{
if(dep[u] > dep[v]) swap(u, v);
for(int k = ; k <= ; k++)//微调,使得dep相等
if((dep[v] - dep[u]) >> k & )
v = fa[k][v];
if(u == v) return u;//公共祖先是u,v中的其中一个
for(int k = ; k >= ; k--)//一起向上跳,先跳距离远的
{
if(fa[k][u] != fa[k][v])
{
u = fa[k][u];
v = fa[k][v];
}
}
return fa[][u];
}
int KTH(int u, int v, int lca, int k)//从u->v路径上的第k个数
{
if(k == ) return u;
int l1 = dep[u] - dep[lca] + ;//左半枝
int l2 = dep[v] - dep[lca];
if(k <= l1)//在左半枝(lca定义成左半枝)
{
k -= ;
for(int t = ; t >= ; t--)
{
if(k >> t & )
u = fa[t][u];
}
return u;
}
else//在右半枝
{
k -= l1;
k = l2 - k;
for(int t = ; t >= ; t--)
{
if(k >> t & )
v = fa[t][v];
}
return v;
}
}
int main ()
{
scanf("%d", &T);
while(T--)
{
init();
int u, v, ds, k;
char s[];
scanf("%d", &N);
for(int i = ; i < N; i++)
{
scanf("%d%d%d", &u, &v, &ds);
add(u, v, ds);
add(v, u, ds);
}
INIT();
while(scanf("%s", s))
{
if(!strcmp(s, "DONE"))
break;
else if(!strcmp(s, "DIST"))
{
scanf("%d%d", &u, &v);
printf("%d\n", dis[u] + dis[v] - * dis[LCA(u, v)]);
}
else
{
scanf("%d%d%d", &u, &v, &k);
int lca = LCA(u, v);
printf("%d\n", KTH(u, v, lca, k)); }
}
}
return ;
}

SPOJ375 Query on a tree 【倍增,在线】的更多相关文章

  1. SPOJ375 Query on a tree

    Description You are given a tree (an acyclic undirected connected graph) with N nodes, and edges num ...

  2. SPOJ375 Query on a tree(树链剖分)

    传送门 题意 给出一棵树,每条边都有权值,有两种操作: 把第p条边的权值改为x 询问x,y路径上的权值最大的边 code #include<cstdio> #include<algo ...

  3. SPOJ375 Query on a tree(LCT边权)

    之前做了两道点权的LCT,这次做一下边权的LCT.上网找了一下资料,发现对于边权的LCT有这么两种处理方法,一种是每条边建一个点,于是边权就转成点权了.另外一种则是每个边权对应到点权上,也就是每个点对 ...

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

  5. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

  6. SPOJ 375. Query on a tree (树链剖分)

    Query on a tree Time Limit: 5000ms Memory Limit: 262144KB   This problem will be judged on SPOJ. Ori ...

  7. QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树

    Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...

  8. spoj 375 Query on a tree(树链剖分,线段树)

      Query on a tree Time Limit: 851MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Sub ...

  9. bzoj 3637: Query on a tree VI 树链剖分 && AC600

    3637: Query on a tree VI Time Limit: 8 Sec  Memory Limit: 1024 MBSubmit: 206  Solved: 38[Submit][Sta ...

随机推荐

  1. mongoDB与sql聚合操作对应图

    SQL Terms, Functions, and Concepts MongoDB Aggregation Operators WHERE $match GROUP BY $group HAVING ...

  2. 赶快收藏!16款最流行的 JavaScript 框架

    下面为大家介绍 16款最流行的 JavaScript 框架,赶快收藏! 1. jQuery – Javascript框架 jQuery 是最流行的 JavaScript 框架,它简化了HTML 文档遍 ...

  3. 关于aspx.designer.cs的研究

    .aspx文件..aspx.cs文件和.aspx.designer.cs的一些说明 .aspx文件:(页面)书写页面代码.存储的是页面design代码.只是放各个控件的代码,处理代码一般放在.cs文件 ...

  4. C语言与汇编语言对照分析

    游戏通常会包含各种各样的功能,如战斗系统.UI渲染.经济系统.生产系统等,每个系统又包含各式各样子功能,如伤害判定.施法.使用道具.角色移动.玩家之间交易等等.这些游戏功能在代码实现中往往少不了条件判 ...

  5. Caffe提取任意层特征并进行可视化

    现在Caffe的Matlab接口 (matcaffe3) 和python接口都非常强大, 可以直接提取任意层的feature map以及parameters, 所以本文仅仅作为参考, 更多最新的信息请 ...

  6. Unity MMO 参考数值

    贴图格式: iOS :RGBA 32 (pvrtc 4 ) Android : RGB Compresed ETC 4 或 RGBA 32  . DrawCall: 总计Drawcall 平均 100 ...

  7. python中随机数生成

    1.random.random random.random()用于生成一个0到1的随机符小数: 0 <= n < 1.0 2.random.uniform random.uniform的函 ...

  8. bugku数字验证绕过正则

    题目:http://120.24.86.145:9009/21.php 第6行使用正则匹配如果匹配到$password开头12个字符中有空格则输出flag并执行exit; 12行是正则匹配$passw ...

  9. Elasticsearch5.0 安装问题集锦【转】

    转自 Elasticsearch5.0 安装问题集锦 - 代码&优雅着&生活 - 博客园http://www.cnblogs.com/sloveling/p/elasticsearch ...

  10. 《secret》读书笔记

    这是在从大连到深圳飞机上看完的一本书,也是大学毕业时室友整理书籍给我的.正好回来的途中,一气呵成读完了. 全书讲了几个事情,其中费了很大篇幅就围绕一个主题,当然书题了——秘密,这个秘密就是“吸引力法则 ...