zoukankan      html  css  js  c++  java
  • LCA上的RMQ模板算法

    How far away ?

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 10764    Accepted Submission(s): 3923


    Problem Description
    There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
     
    Input
    First line is a single integer T(T<=10), indicating the number of test cases.
      For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
      Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
     
    Output
    For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.
     
    Sample Input
    2 3 2 1 2 10 3 1 15 1 2 2 3 2 2 1 2 100 1 2 2 1
     
    Sample Output
    10 25 100 100
     
     
    这题可以用离线算法做,我这里介绍的是RMQ算法 。。
    RMQ算法就是求区间最值问题的算法,这里用到最近公共祖先上面。是根据每个点的编号以及深度来确定最近公共祖先。
    贴模板:
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    #define N 40010
    #define M 205
    
    struct Edge{
        int u,v,w,next;
    }e[2*N];
    int head[N];
    int dp[2*N][20];  ///
    int vis[N];
    int first[N];
    int deep[2*N];  ///记录每个点每次出现出现所在的深度,由于回溯,遂开两倍
    int id[2*N];  ///结点的编号,也会出现两次
    int dis[N];
    int tot;
    
    int MIN(int i,int j){
        if(i>=j) return j;
        return i;
    }
    void add_edge(int u,int v,int w,int & k){
        e[k].u=u;e[k].v=v;e[k].w = w;
        e[k].next=head[u];head[u]=k++;
    }
    void dfs(int u,int d){
        vis[u]=true;id[++tot]=u;first[u]=tot;deep[tot]=d;
        for(int k = head[u];k!=-1;k=e[k].next){
            if(!vis[e[k].v]){
                int v = e[k].v,w = e[k].w;
                dis[v]=dis[u]+w;
                dfs(v,d+1);
                id[++tot]=u,deep[tot]=d;
            }
        }
    }
    void init_RMQ(int n){
        for(int i=1;i<=n;i++){
            dp[i][0]=i; ///保存的是下标
        }
        for(int j=1;(1<<j)<=n;j++){
            for(int i=1;i+(1<<j)-1<n;i++){
                dp[i][j] = MIN(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int RMQ(int L,int R){
        int k=0;
        while((1<<(k+1))<=(R-L+1)) k++;
        int a = dp[L][k],b = dp[R-(1<<k)+1][k];
        if(deep[a]<deep[b]) return a;
        return b;
    }
    int LCA(int L,int R){
        int x = first[L];
        int y = first[R];
        if(x>y) swap(x,y);
        return id[RMQ(x,y)];
    }
    int main()
    {
        int tcase;
        scanf("%d",&tcase);
        while(tcase--){
            memset(head,-1,sizeof(head));
            memset(vis,0,sizeof(vis));
            int n,m;
            scanf("%d%d",&n,&m);
            tot = 0;
            for(int i=1;i<n;i++){
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                add_edge(u,v,w,tot);
                add_edge(v,u,w,tot);
            }
            tot = 0;
            dis[1]=0;
            dfs(1,1);
            init_RMQ(2*n-1);
            while(m--){
                int a,b;
                scanf("%d%d",&a,&b);
                int lca = LCA(a,b);
                printf("%d
    ",dis[a]+dis[b]-2*dis[lca]);
            }
        }
        return 0;
    }
  • 相关阅读:
    leetcode167 Two Sum II
    leetcode18 4Sum
    leetcode15 three sum
    leetcode-1-Two Sum
    SQL优化——select
    Hadoop 集群搭建
    虚拟机中的两台主机怎么相互拷贝文件
    doker5
    docker4
    docker3
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5346140.html
Copyright © 2011-2022 走看看