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的,然后用倍增法找到那个点即可。

代码如下:

#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
using namespace std;
#define LL long long
#define PI acos(-1.0)
const int mod=1e7+3;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
const int MAXN=10000+10;
int dep[MAXN], dis[MAXN], dp[MAXN][30];
int head[MAXN], cnt, n;
struct node
{
        int u, v, w, next;
}edge[MAXN<<1];
void add(int u, int v, int w)
{
        edge[cnt].v=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt++;
}
void dfs(int u, int fa)
{
        for(int i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].v;
                if(v==fa) continue ;
                dep[v]=dep[u]+1;
                dis[v]=dis[u]+edge[i].w;
                dfs(v,u);
                dp[v][0]=u;
        }
}
struct BZ
{
        int i, j;
        void init()
        {
                for(j=1;(1<<j)<=n;j++){
                        for(i=1;i<=n;i++){
                                if(dp[i][j-1]!=-1)
                                dp[i][j]=dp[dp[i][j-1]][j-1];
                        }
                }
        }
        int Query(int u, int v)
        {
                if(dep[u]<dep[v]) swap(u,v);
                for(i=0;(1<<i)<=dep[u];i++) ;
                i--;
                for(j=i;j>=0;j--){
                        if(dep[u]-(1<<j)>=dep[v])
                                u=dp[u][j];
                }
                if(u==v) return u;
                for(j=i;j>=0;j--){
                        if(dp[u][j]!=dp[v][j]){
                                u=dp[u][j];
                                v=dp[v][j];
                        }
                }
                return dp[u][0];
        }
        int kth(int u, int v, int k)
        {
                int root=Query(u,v), ans;
                if(dep[u]-dep[root]+1>=k){
                        ans=dep[u]-k+1;
                        for(i=0;(1<<i)<=dep[u];i++) ;
                        i--;
                        for(j=i;j>=0;j--){
                                if(dep[u]-(1<<j)>=ans)
                                        u=dp[u][j];
                        }
                        return u;
                }
                else{
                        ans=dep[root]+k-(dep[u]-dep[root]+1);
                        for(i=0;(1<<i)<=dep[v];i++) ;
                        i--;
                        for(j=i;j>=0;j--){
                                if(dep[v]-(1<<j)>=ans)
                                        v=dp[v][j];
                        }
                        return v;
                }
        }
}bz;
void init()
{
        memset(head,-1,sizeof(head));
        memset(dep,0,sizeof(dep));
        memset(dis,0,sizeof(dis));
        memset(dp,-1,sizeof(dp));
        cnt=0;
}
int main()
{
        int T, i, u, v, w, k;
        char s[10];
        scanf("%d",&T);
        while(T--){
                scanf("%d",&n);
                init();
                for(i=1;i<n;i++){
                        scanf("%d%d%d",&u,&v,&w);
                        add(u,v,w);
                        add(v,u,w);
                }
                dfs(1,-1);
                bz.init();
                while(scanf("%s",s)!=EOF&&s[1]!=‘O‘){
                        if(s[1]==‘I‘){
                                scanf("%d%d",&u,&v);
                                printf("%d\n",dis[u]+dis[v]-2*dis[bz.Query(u,v)]);
                        }
                        else{
                                scanf("%d%d%d",&u,&v,&k);
                                printf("%d\n",bz.kth(u,v,k));
                        }
                }
        }
        return 0;
}
时间: 2024-10-13 11:52:07

SPOJ 913 QTREE系列- Query on a tree II (倍增LCA)的相关文章

SPOJ 375 QTREE系列-Query on a tree (树链剖分)

题目地址:SPOJ 375 树链剖分第一发! 果然是个貌似很高级的数据结构,其实就是把树的边从树形结构转化成了线性结构,从而可以用线段树或树状数组之类的数据结构进行快速维护.从而将时间缩到n*log(2*n). 这题用的线段树维护的. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #incl

【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

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 - QTREE 375 Query on a tree 树链剖分+线段树

操作1:修改第k条边权. 操作2:询问两点间最大边权. 树链剖分,然后线段树维护最大值 #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<queue> #include<vector> #inclu

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 题目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

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 <iost

SPOJ QTREE 375. Query on a tree

SPOJ Problem Set (classical) 375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHA

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