• 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;
    }
  • 相关阅读:
    偏函数
    装饰器
    排序
    匿名函数
    参数传递
    pass语句
    不定长函数
    通用函数
    不定长参数(元祖)
    不定长参数(字典)
  • 原文地址:https://www.cnblogs.com/WindFreedom/p/9471532.html
Copyright © 2020-2023  润新知