zoukankan      html  css  js  c++  java
  • 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("");
        }
    }
    

      

    也许有挫折,但这些,怎能挡住湘北前进的步伐
  • 相关阅读:
    asp.net发布到IIS中出现错误:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”
    System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes”
    禁止tableview 像上滑动
    IOS 贝塞尔曲线切割圆角
    头像图片裁剪
    iOS 限制TextField输入长度
    根据经纬度反向地理编译出地址信息(如果报错:Error Domain=kCLErrorDomain Code=8 "(null)")
    空白页界面
    NSPhotoLibraryAddUsageDescription解决办法
    IOS字符串截取保留小数点后两位
  • 原文地址:https://www.cnblogs.com/Fatedayt/p/2584441.html
Copyright © 2011-2022 走看看