zoukankan      html  css  js  c++  java
  • FZU 2207 ——以撒的结合——————【LCA + 记录祖先】

    Problem 2207 以撒的结合

    Accept: 47    Submit: 161
    Time Limit: 1000 mSec    Memory Limit : 32768 KB

     Problem Description

    小茗同学最近在认真地准备比赛,所以经常玩以撒的结合。

    《以撒的结合》是一款由Edmund McMillen,Florian Himsl 开发,并由Edmund McMillen最早于2011年09月29日发行的一款2D平面角色扮演、动作冒险类的独立游戏。游戏的角色将在有着能够提升能力的道具与特殊技能的半RPG世界中闯荡。

    ——来自百度百科

    小茗同学在打BOSS前,费掉了很多HP。在地图的一些房间里有补充HP的红心,然而小茗同学受到了看不见地图的诅咒。凭借不知道哪里来的记忆,小茗同学记得某个有红心的房间在房间A与房间B的路上的第K个房间里。为了简化问题,我们把地图看成一棵树。小茗同学想知道A到B的第K个房间号为多少,由于小茗同学很累,所以现在这个任务交给你了。

     Input

    第一行是一个整数T(T<=10),表示有T组测试数据。

    每组数据的第一行为两个整数n m(0<n<=1000,0<m<=n*n),分别表示房间个数和询问次数。

    接下来n-1行,每行两个整数u v(0<u、v<=n,且u≠v),表示地图上房间u和房间v有一条路径。

    最后是m行,每行三个整数u v k,表示询问房间u到房间v的路径上的第k个房间。

    输入数据保证合法,即k不超过u、v的最短距离。

     Output

    对于每组数据,首先第一行先输出“Case #x:“ ,其中x是从1开始,表示数据组号,接下来m行,每行输出相应的房间号。

     Sample Input

    1
    6 3
    1 2
    2 4
    2 5
    1 3
    3 6
    4 6 4
    1 6 2
    4 5 3

     Sample Output

    Case #1:
    3
    3
    5

     Source

    FOJ有奖月赛-2015年11月
     
     
    解题思路:首先我们求出u,v两点的LCA为x,然后来判断出k在u-x段还是在v-x段。然后记录每个点u与祖先ancestor的距离,然后O(1)查询。
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<vector>
    #include<math.h>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<string>
    #include<stdlib.h>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    #define mid (L+R)/2
    #define lson rt*2,L,mid
    #define rson rt*2+1,mid+1,R
    const int maxn = 1300;
    const LL mod = 1000000007;
    const int INF = 0x3f3f3f3f;
    struct AdjEdge{
        int to,w,next;
    }adjedges[maxn*2];
    int head[maxn];
    int vset[maxn*2],dep[maxn],d[maxn*2][30],first[maxn];
    int fa[maxn][maxn];
    int tot,nn;
    void init(){
        tot=0;
        nn=0;
        memset(dep,0,sizeof(dep));
        memset(head,-1,sizeof(head));
        memset(d,0,sizeof(d));
        memset(first,0,sizeof(first));
    }
    void addedge(int _u,int _v){     //
        adjedges[tot].to=_v;
        adjedges[tot].next=head[_u];
        head[_u]=tot++;
    //    adjedges[tot].to=_u;
    //    adjedges[tot].next=head[_v];
    //    head[_v]=tot++;
    }
    
    void dfs(int _u,int _fa,int _dep){
       // printf("%d %d
    ",_u,_dep);
        dep[_u]=_dep;
        vset[++nn]=_u;
        first[_u]=nn;
        fa[_u][0] = _u;
        for(int i = 1; i <= _dep; i++){
            fa[_u][i] = fa[_fa][i-1];
        }
        for(int i=head[_u];i!=-1;i=adjedges[i].next){
            AdjEdge & e = adjedges[i];
            if(e.to!=_fa){
                dfs(e.to,_u,_dep+1);
                vset[++nn]=_u;
            }
        }
    }
    void ST(){
        for(int i=1;i<=nn;i++)
            d[i][0]=vset[i];
        for(int j=1; (1<<j)<=nn; j++){
            for(int i=1; i+(1<<j)-1<=nn; i++){
                if(dep[d[i][j-1]]<dep[d[i+(1<<(j-1))][j-1]])
                    d[i][j]=d[i][j-1];
                else d[i][j]=d[i+(1 << (j-1))][j-1];
            }
        }
    }
    
    int RMQ(int L,int R){
        int k=0;
        while((1<<(k+1))<=R-L+1) k++;
        if(dep[d[L][k]]<=dep[d[R-(1<<k)+1][k]])
            return d[L][k];
        return d[R-(1<<k)+1][k];
    }
    void tes(){
        for(int i =1; i <= 7; i++){
            for(int j = 0; j <= 4; j++){
                printf("%d ",fa[i][j]);
            }puts("");
        }
    }
    int main(){
        int T, n, q, cas = 0;
        scanf("%d",&T);
        while(T--){
            init();
            int a,b,k;
            scanf("%d%d",&n,&q);
            for(int i=1; i<n; i++){
                scanf("%d%d",&a,&b);
                addedge(a,b);
                addedge(b,a);
            }
            memset(fa,0,sizeof(fa));
            dfs(1,0,1);    //dep 1
            ST();
         //   tes();
            printf("Case #%d:
    ",++cas);
            int x;
            for(int i=0; i<q; i++){
                scanf("%d%d%d",&a,&b,&k);
                if(first[a]<=first[b]){
                    x = RMQ(first[a],first[b]);
                }else{
                    x = RMQ(first[b],first[a]);
                }
                if(k == 1){
                    printf("%d
    ",a);
                }else if(dep[a] + dep[b] - 2*dep[x] + 1 == k){
                    printf("%d
    ",b);
                }else if(dep[a] - dep[x] + 1 >= k){
                    printf("%d
    ",fa[a][k-1]);
                }else{
                    int kk = dep[a] + dep[b] - 2*dep[x] - k + 1;
                    printf("%d
    ",fa[b][kk]);
                }
            }
        }
        return 0;
    }
    
    /*
    55
    7 10
    1 2
    1 3
    2 4
    2 5
    5 6
    5 7
    
    4 3 3
    4 3 2
    7 4 3
    4 7 3
    4 7 4
    
    */
    

      

     
     
  • 相关阅读:
    【HTML5校企公益课】第二天
    【Python】IO编程
    【HTML5校企公益课】第一天
    【c++ primer, 5e】构造函数 & 拷贝、赋值和析构
    【c++ primer, 5e】定义类相关的非成员函数
    NHibernate -- HQL
    SQL 根据时间和打印状态抽取记录
    下载工具
    NHibernate
    使用代码辅助生成工具CodeSmith -- 生成NHibernate的映射文件
  • 原文地址:https://www.cnblogs.com/chengsheng/p/5288003.html
Copyright © 2011-2022 走看看