zoukankan      html  css  js  c++  java
  • hdu2856(倍增lca模版题)

    ac代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define per(i,a,b) for(int i=a;i <= b;i++)
    #define Max(a,b) a=max(a,b)
    #define Min(a,b) a=min(a,b)
    #define Sz(x) (int)x.size()
    typedef long long ll;
    ll gcd(ll a,ll b){while(b){ll t=b;b=a%b;a=t;}return a;}
    const int inf=0x3f3f3f3f;
    const int mod=1000000007;
    #define siz 40005
    int T,n,m,mul_fa[siz][16],jdis[siz][16],depth[siz];//mul_fa[]表示倍增祖先,jdis[]表示向上跳2^i步的权(距离)
    int head[siz],Enum=0,N;//N最多能跳的2^i个祖先,N设为log2(n)是因为就算退化成单链,根据倍增最多条log2(n)
    struct node{int to,w,ne;}edge[siz*2];
    void add_edge(int a,int b,int k){
        edge[Enum].to=b;
        edge[Enum].w=k;
        edge[Enum].ne=head[a];
        head[a]=Enum++;
    }
    void init()
    {
        Enum=0;
        memset(head,-1,sizeof(head));
    }
    void dfs(int u,int pre)
    {
        for(int i=1;i<=N;i++){
            mul_fa[u][i]=mul_fa[mul_fa[u][i-1]][i-1];
            jdis[u][i]=jdis[u][i-1]+jdis[mul_fa[u][i-1]][i-1];
        }
        for(int i=head[u];i!=-1;i=edge[i].ne){
            int v=edge[i].to;
            if(v==pre)continue;
            depth[v]=depth[u]+1;
            mul_fa[v][0]=u;
            jdis[v][0]=edge[i].w;
            dfs(v,u);
        }
    }
    void lca_init()
    {
        N=floor((int)log2(n*1.0));
        depth[1]=0;
        memset(mul_fa,0,sizeof(mul_fa));
        memset(jdis,0,sizeof(jdis));
        dfs(1,-1);//以1为根节点建树
    }
    int LCA(int a,int b)
    {
        if(depth[a] < depth[b])swap(a,b);
        int ans=0;
        for(int i=N;i>=0;i--){
            if(depth[a]>depth[b] && depth[a]-(1<<i)>=depth[b]){
                ans+=jdis[a][i];
                a=mul_fa[a][i];
            }
        }
        for(int i=N;i>=0;i--){
            if(mul_fa[a][i]!=mul_fa[b][i]){
                ans+=(jdis[a][i]+jdis[b][i]);
                a=mul_fa[a][i];
                b=mul_fa[b][i];
            }
        }
        if(a!=b){ans+=(jdis[a][0]+jdis[b][0]);}
        return ans;
    }
    
    int main()
    {
        scanf("%d",&T);
        while(T--){
            int a,b,k;
            scanf("%d%d",&n,&m);
            init();
            for(int i=1;i<=n-1;i++){
                scanf("%d %d %d",&a,&b,&k);
                add_edge(a,b,k);add_edge(b,a,k);
            }
            lca_init();
            for(int i=1;i<=m;i++){
                scanf("%d %d",&a,&b);
                printf("%d
    ",LCA(a,b));
            }
        }
    
        return 0;
    }
  • 相关阅读:
    Photoshop色阶、曲线命令图解和编程实现(附源码)
    苹果Mac OS X快捷键大全
    lucene Field部分参数设置含义
    图片管理下载逻辑
    Lucene.Net无障碍学习和使用:索引篇 (转)
    Firebug 调试器开发中的12个技巧
    Lucene.Net 多线程操作建议(转)
    如何在ASP.NET中下载文件
    Lucene.Net 2.3.1开发介绍 —— 简介 (转)
    JS打开图片另存为对话框 (转)
  • 原文地址:https://www.cnblogs.com/WindFreedom/p/9471532.html
Copyright © 2011-2022 走看看