首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【SPOJ QTREE2】QTREE2 - Query on a tree II(LCA)

【SPOJ QTREE2】QTREE2 - Query on a tree II(LCA)

作者头像
饶文津
发布2020-06-02 10:52:35
发布2020-06-02 10:52:35
39800
代码可运行
举报
文章被收录于专栏:饶文津的专栏饶文津的专栏
运行总次数:0
代码可运行

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

代码语言:javascript
代码运行次数:0
运行
复制
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

 Submit solution!

 先以一点为根做dfs,计算每个点的深度、父亲、离根的距离,倍增法找出LCA,两点的距离就能算出来了。

路径上的第K个值则先判断LCA到起点的深度差是否大于k,是则在起点到LCA的路径上,否则在LCA到终点的路径上。

代码语言:javascript
代码运行次数:0
运行
复制
#include <iostream>
#include <cstdio>
#include <cstring>
#define N 10005
using namespace std;
struct edge{
    int to,next,w;
}e[N<<1];
int head[N],cnt;
void add(int u,int v,int w){
    e[++cnt]=(edge){v,head[u],w};
    head[u]=cnt;
}
int n;
int deep[N],dis[N],p[N][30];
void dfs(int x,int fa){
    deep[x]=deep[fa]+1;
    p[x][0]=fa;
    for(int i=0;p[x][i];i++)
        p[x][i+1]=p[p[x][i]][i];//由x的2^i祖先和祖先的2^i祖先算出x的2^(i+1)祖先
    for(int i=head[x];i;i=e[i].next){
        int to=e[i].to;
        if(to==fa)continue;
        dis[to]=dis[x]+e[i].w;
        dfs(to,x);
    }
}
int lca(int a,int b){
    if(deep[a]<deep[b])swap(a,b);
    for(int j=14;j>=0;j--)
    if(deep[a]-(1<<j)>=deep[b])//将a上移到和b深度一样
        a=p[a][j];
    if(a==b)return a;
    for(int j=14;j>=0;j--)
        if(p[a][j]&&p[a][j]!=p[b][j]){//a、b一起上移
            a=p[a][j];
            b=p[b][j];
        }
    return p[a][0];
}
int get(int u,int d){//u上升到d深度
    for(int j=14;j>=0;j--)
    if(deep[u]-(1<<j)>=d)
        u=p[u][j];
    return u;
}
int main() {
    int t;
    cin>>t;
    while(t--){
        memset(head,0,sizeof head);
        memset(p,0,sizeof p);//这个要清空!!
        cnt=0;
        cin>>n;
        for(int i=1;i<n;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
        }
        //deep[0]=0;dis[1]=0;这可以不写
        dfs(1,0);
        char op[100];
        while(1){
            scanf("%s",op);
            if(op[1]=='O')break;
            if(op[1]=='I'){
                int u,v;
                scanf("%d%d",&u,&v);
                printf("%d\n",dis[u]+dis[v]-2*dis[lca(u,v)]);
            }else{ 
                int u,v,k;
                scanf("%d%d%d",&u,&v,&k);
                int fa=lca(u,v),d;
                if(deep[u]-deep[fa]<k){
                    d=deep[fa]+k-(deep[u]-deep[fa]+1);
                    u=v;
                }
                else d=deep[u]-k+1;//需要的深度
                printf("%d\n",get(u,d));
            }
        }
    }
}
  
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-08-31 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Input
  • Output
  • Example
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档