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至点b有向路径上的第k个点的编号

有多组测试数据,每组数据以DONE结尾。

裸的LCA。

在处理第二个操作时,我直接向上数跳了多少个。

顾z大佬说不能这么做,要求出跳到那个点的深度再去跳。

真的是这样,不过懒得想了,应该是+1-1的误差。 balabala。。。

code:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int wx=50017;

int dep[wx],dis[wx];
int f[wx][23];
int head[wx];
int num,n,t;
char opt[7];

inline int read(){
    int sum=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    return sum*f;
}

struct e{
    int nxt,to,dis;
}edge[wx*2];

void add(int from,int to,int dis){
    edge[++num].nxt=head[from];
    edge[num].to=to;
    edge[num].dis=dis;
    head[from]=num;
}

void dfs(int u,int fa){
    dep[u]=dep[fa]+1;
    for(int i=head[u];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(v==fa)continue;
        f[v][0]=u;dis[v]=dis[u]+edge[i].dis;
        dfs(v,u);
    }
}

void pre(){
    for(int j=1;j<=21;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];
}

int LCA(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int i=21;i>=0;i--){
        if(dep[f[x][i]]>=dep[y]){
            x=f[x][i];
        }
    }
    if(x==y)return x;
    for(int i=21;i>=0;i--){
        if(f[x][i]!=f[y][i]){
            x=f[x][i]; y=f[y][i];
        }
    }
    return f[x][0];
}

int find(int x,int k){
    for(int i=21;i>=0;i--){
        if(dep[f[x][i]]>=k)x=f[x][i];
    }
    return x;
}

int main(){
    t=read();
    while(t--){
        n=read();
        memset(head,0,sizeof head); num=1;
        memset(edge,0,sizeof edge);
        for(int i=1;i<n;i++){
            int x,y,z;
            x=read(); y=read(); z=read();
            add(x,y,z); add(y,x,z);
        }
        dfs(1,0); pre();
        while(1){
            scanf("%s",opt+1);
            if(opt[2]=='O')break;
            if(opt[2]=='I'){
                int x,y;
                x=read(); y=read();
                int lca=LCA(x,y);
                printf("%d\n",dis[x]+dis[y]-2*dis[lca]);
            }
            if(opt[1]=='K'){
                int a,b,k;
                a=read(); b=read(); k=read();
                int lca=LCA(a,b);
                if(dep[a]-dep[lca]+1>=k)printf("%d\n",find(a,dep[a]-k+1));
                else printf("%d\n",find(b,k-dep[a]+2*dep[lca]-1));
            }
        }
    }
}

原文地址:https://www.cnblogs.com/wangxiaodai/p/9858833.html

时间: 2024-10-11 21:15:34

LCA SP913 QTREE2 - Query on a tree II的相关文章

SP913 QTREE2 - Query on a tree II

嘟嘟嘟 LCA水题,第二问看一下\(x\)到\(lca\)的路径长度是否够\(k - 1\),不过的话就从\(y\)出发往上跳. #include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector>

SPOJ QTREE2 Query on a tree II

Query on a tree II Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: QTREE264-bit integer IO format: %lld      Java class name: Main You are given a tree (an undirected acyclic connected graph) with N nodes,

【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...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: D

SPOJ 913 QTREE系列- Query on a tree II (倍增LCA)

题目地址:QTREE2 - Query on a tree II LCA学了离线与在线转RMQ方法后就去做这道题,于是想了好长时间也没想到怎么做.看了题解都是用的倍增LCA..于是又去学了下倍增法求LCA,这才发现用倍增法做简直是水题...因为求路径的第k个点可以转化成求第k个父节点,然而倍增法的原理就是根据的父节点,于是这题就很容易解决了.. 求距离很好求.关键是求路径第k个点,显然这个点要么是u的第k个父节点,要么是v的第k个父节点,于是乎,先求一次LCA,判断是u还是v的,然后用倍增法找到

SPOJ 题目913QTREE2 - Query on a tree II(Link Cut Tree 查询路径第k个点)

QTREE2 - Query on a tree II no tags 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 i

SPOJ-QTREE2 Query on a tree II(暴力+LCA)

题目大意:给出一棵树,3种操作 DIST u,v 询问u到v的距离 KTH k, u, v 询问u到v的路径上的第k大的边的权值 解题思路:刚开始以为会爆,结果发现不会 直接暴力存储u到v的路上的所有边,再进行排序,输出第k大的边即可 #include <cstdio> #include <cstring> #define N 10010 struct Edge{ int to, next, cost; }E[2*N]; int head[N], depth[2 * N], fir

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...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: D

SPOJ 913 Query on a tree II ( 树链剖分 + 倍增 )

题目链接~~> 做题感悟:感觉又充实了一些. 解题思路:树链剖分 + 倍增 开始看时,第一问还好,第二问就不知道怎么解了.其实这两问都可以用倍增法解决. 先解释一下我理解的倍增 :记录 u 结点的 第 2 ^ i 个祖先,然后求u 的第 k 个祖先的时候,就相当于用 2 ^ i 去组合 k ,不断向上,一直到达第 k 个节点,其实每次更新的时k 的二进制中为 1 的位置.如下图,计算 u 的第 5 个祖先结点(这里不包括 u),先到达 u' 节点,然后再从 u' ,到 u'' (5 的二进制 1

SPOJ913 Query on a tree II

Time Limit: 433MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description 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, represe