• SPOJ 913. Query on a tree II


    SPOJ Problem Set (classical)

    SPOJ 913. Query on a tree II

    Problem code: QTREE2

     

     

    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 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
    -------------------------------------------------------------------
    题目大意:给定一颗有边权的树,有两种操作,DIST(i,j)操作询问i和j节点之间的距离,KTH(i,j,k)操作询问i和j节点之间第k个节点的编号。
    解题思路:利用树上的倍增就可以搞定。每个节点都保存它的第2^i的父亲。对于DIST询问,只要利用倍增求出lca,然后减一减就好了。对于KTH询问,先求出lca,然后判断是第一个点到lca的路径上还是第二个点到lca的路径上。哎算是水题,不过第一次用倍增,RE好久。
    #include <stdio.h>
    #include <string.h>
    #include <vector>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    
    const int N=200005;
    int n,eid;
    int head[N],ed[N<<1],val[N<<1],nxt[N<<1];
    vector<int>fa[N];
    int sta[N],top,dep[N],dis[N];
    
    void addedge(int s,int e,int v){
        ed[eid]=e;val[eid]=v;nxt[eid]=head[s];head[s]=eid++;
    }
    
    void dfs(int s,int f,int d,int ds){
        fa[s].clear();int k=1;dep[s]=d;dis[s]=ds;
        while(top-k>=0){
            fa[s].push_back(sta[top-k]);k*=2;
        }
        sta[top++]=s;
        for(int i=head[s];~i;i=nxt[i]){
            int e=ed[i],v=val[i];
            if(e!=f)dfs(e,s,d+1,ds+v);
        }
        top--;
    }
    
    int lca(int a,int b){
        if(a==b)return a;
        if(dep[b]>dep[a])swap(a,b);
        while(dep[a]>dep[b]){
            int len=fa[a].size(),le=0,ri=len,mid;
            while(mid=(le+ri)>>1,ri>le){
                if(dep[fa[a][mid]]>=dep[b])le=mid+1;
                else ri=mid;
            }
            a=fa[a][ri-1];
        }
        if(a==b)return a;
        while(1){
            int len=fa[a].size(),le=0,ri=len,mid;
            while(mid=(le+ri)>>1,ri>le){
                if(fa[a][mid]!=fa[b][mid])le=mid+1;
                else ri=mid;
            }
            if(ri==0)return fa[a][ri];
            a=fa[a][ri-1];b=fa[b][ri-1];
        }
        return a;
    }
    
    int kth(int a,int b,int k){
        int r=lca(a,b);
        if(dep[a]-dep[r]+1>=k){
            int u=dep[a]-k+1;
            while(1){
                if(u==dep[a])return a;
                int len=fa[a].size(),le=0,ri=len,mid;
                while(mid=(le+ri)>>1,ri>le){
                    if(dep[fa[a][mid]]>=u)le=mid+1;
                    else ri=mid;
                }
                a=fa[a][ri-1];
            }
        }
        else{
            int u=k-dep[a]+dep[r]*2-1;
            while(1){
                if(u==dep[b])return b;
                int len=fa[b].size(),le=0,ri=len,mid;
                while(mid=(le+ri)>>1,ri>le){
                    if(dep[fa[b][mid]]>=u)le=mid+1;
                    else ri=mid;
                }
                b=fa[b][ri-1];
            }
        }
    }
    
    int main(){
    //    freopen("/home/axorb/in","r",stdin);
        int T;scanf("%d",&T);
        while(T--){
            eid=0;clr(head,-1);scanf("%d",&n);
            for(int i=1;i<n;i++){
                int a,b,c;scanf("%d%d%d",&a,&b,&c);
                addedge(a,b,c);addedge(b,a,c);
            }
            top=0;dfs(1,-1,1,0);
    //        for(int i=1;i<=n;i++)printf("%d %d %d\n",i,fa[i].size(),dep[i]);
            char ss[20];
            while(scanf("%s",ss),ss[1]!='O')
                if(ss[1]=='I'){
                    int a,b;scanf("%d%d",&a,&b);
                    int r=lca(a,b);
                    printf("%d\n",dis[a]+dis[b]-2*dis[r]);
                }
                else{
                    int a,b,c;scanf("%d%d%d",&a,&b,&c);
                    printf("%d\n",kth(a,b,c));
                }
            puts("");
        }
    }
    

      

    也许有挫折,但这些,怎能挡住湘北前进的步伐
  • 相关阅读:
    C#中利用iTextSharp开发二维码防伪标签(1)
    delphi 数据库中Connection与Query连接数量问题思考
    cPanel 安装方法
    招商行用卡人工服务方式
    软链接的创建和查看
    zencart低版本由php5.2.17升级PHP5.3环境下错误及解决方案
    EXCEL应用:高级筛选里的条件或和与的条件怎么写 例:不包含,包含等
    array_walk与array_map 的不同 array_filter
    zen cart global $db 这噶哒
    hdu 5655 CA Loves Stick
  • 原文地址:https://www.cnblogs.com/Fatedayt/p/2584441.html
Copyright © 2020-2023  润新知