zoukankan      html  css  js  c++  java
  • caioj 1237: 【最近公共祖先】树上任意两点的距离 在线倍增ST

    caioj 1237: 【最近公共祖先】树上任意两点的距离 倍增ST

    题目链接:http://caioj.cn/problem.php?id=1237

    思路:

    • 针对询问次数多的时候,采取倍增求取LCA,同时跟新距离数组
    • 因为
    • (2^{14} > 10000)
    • 所以所以表示祖先的数组dp[][]第二维取到14即可

    代码:

    #include <iostream>
    #include <algorithm>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    using namespace std;
    const int maxn = 10005;
    const int maxm = 20005;
    struct node {
        int to,next,w;
    }edges[maxm];
    int head[maxn],cnt,dp[maxn][15],dep[maxn],dist[maxn];
    void addedge(int u, int v, int w) {
        edges[cnt].to=v;
        edges[cnt].w=w;
        edges[cnt].next=head[u];
        head[u]=cnt++;
    }
    void dfs(int s, int x) {
        dep[s]=dep[x]+1;
        dp[s][0]=x;
        int t;
        for(int i=1;(1<<i)<=dep[s];++i)
            dp[s][i]=dp[dp[s][i-1]][i-1];
        for(int i=head[s];i!=-1;i=edges[i].next) {
            t=edges[i].to;
            if(t==x) continue;
            dist[t]=dist[s]+edges[i].w;
            dfs(t,s);
        }
    }
    int lca(int u, int v) {
        if(dep[v]>dep[u]) swap(u,v);
        for(int i=14;i>=0;--i) {
            if((1<<i)<=(dep[u]-dep[v])) {
                u=dp[u][i];
            }
        }
        if(u==v) return u;
        for(int i=14;i>=0;--i) {
            if((1<<i)<=dep[u]&&(dp[u][i]!=dp[v][i])) {
                u=dp[u][i];
                v=dp[v][i];
            }
        }
        return dp[u][0];
    }
    int slove(int u ,int v) {
        int z=lca(u,v);
        return dist[u]-2*dist[z]+dist[v];
    }
    void init() {
        cnt=0;
        memset(head,-1,sizeof(head));
    }
    int main() {
        int n,m,u,v,w;
        scanf("%d %d",&n,&m);
        init();
        for(int i=1;i<n;++i) {
            scanf("%d %d %d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        dep[1]=0;//为了统一dfs的写法,实际dep[1]=1
        dp[1][0]=1;
        dfs(1,1);
        for(int i=1;i<=m;++i) {
            scanf("%d %d",&u,&v);
            printf("%d
    ",slove(u,v));
        }
        return 0;
    }
    
  • 相关阅读:
    win32程序添加控制台程序
    STL链表类模板的学习
    简单封装的串口通信类
    nyoj49 开心的小明
    hdu2094 产生冠军
    hdu1272 小希的迷宫
    hdu1106 排序
    hdu1999 不可摸数
    hdu2085 核反应堆
    nyoj119 士兵杀敌(三)
  • 原文地址:https://www.cnblogs.com/lemonbiscuit/p/7878994.html
Copyright © 2011-2022 走看看