zoukankan      html  css  js  c++  java
  • 可用倍增LCA解题

    http://codevs.cn/problem/2370/

    #include<bits/stdc++.h>
    using namespace std;
    const int M=5e4+5;
    const int N=20;
    struct node{
        int v,w;
        node(int vv=0,int ww=0):v(vv),w(ww){}
    };
    vector<node>e[M];
    int n,grand[M][N],dis[M][N],deep[M],book[M],root,s;
    void dfs(int u){
        for(int i=1;i<=s;i++){
            grand[u][i]=grand[grand[u][i-1]][i-1];
            dis[u][i]=dis[u][i-1]+dis[grand[u][i-1]][i-1];
            if(!grand[u][i])
                break;
        }
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i].v;
            if(v!=grand[u][0]){
                grand[v][0]=u;
                deep[v]=deep[u]+1;
                dis[v][0]=e[u][i].w;
                dfs(v);
            }
        }
    }
    void init(){
        s=floor(log(1.0*n)/log(2.0));
        deep[0]=-1;
        dfs(root);
    }
    int LCA(int a,int b){
        if(deep[a]>deep[b])
            swap(a,b);
        int ans=0;
        for(int i=s;i>=0;i--){
            if(deep[a]<deep[b]&&deep[a]<=deep[grand[b][i]])
                ans+=dis[b][i],b=grand[b][i];
        }
        for(int i=s;i>=0;i--){
            if(grand[a][i]!=grand[b][i])
                ans+=dis[a][i],ans+=dis[b][i],a=grand[a][i],b=grand[b][i];
        }
        if(a!=b)
            ans+=dis[a][0]+dis[b][0];
        return ans;
    }
    int main(){
    
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            u++;
            v++;///fu
            book[u]=1;
            e[u].push_back(node(v,w));
            e[v].push_back(node(u,w));
        }
        for(int i=1;i<=n;i++){
            if(!book[i]){
                root=i;
                break;
            }
        }
        init();
        int m;
        scanf("%d",&m);
        while(m--){
            int u,v;
            scanf("%d%d",&u,&v);
            u++,v++;
            printf("%d
    ",LCA(u,v));
        }
        return 0;
    }
    View Code

    http://codevs.cn/problem/1036/

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    const int M=3e4+4;
    const int N=20;
    struct node{
        int v,w;
        node(int vv=0,int ww=0):v(vv),w(ww){}
    };
    vector<node>e[M];
    int s,grand[M][N],dis[M][N],book[M],deep[M],root,n;
    void dfs(int u){
        for(int i=1;i<=s;i++){
            grand[u][i]=grand[grand[u][i-1]][i-1];
            dis[u][i]=dis[u][i-1]+dis[grand[u][i-1]][i-1];
            if(!grand[u][i])
                break;
        }
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i].v;
            if(v!=grand[u][0]){
                grand[v][0]=u;
                deep[v]=deep[u]+1;
                dis[v][0]=e[u][i].w;
                dfs(v);
            }   // cout<<"!!"<<endl;
        }
    }
    void init(){
        s=floor(log(1.0*n)/log(2.0));
        deep[0]=-1;
        dfs(root);
    }
    int LCA(int a,int b){
        if(deep[a]>deep[b])
            swap(a,b);
        int ans=0;
        for(int i=s;i>=0;i--){
            if(deep[b]>deep[a]&&deep[a]<=deep[grand[b][i]])
                ans+=dis[b][i],b=grand[b][i];
        }
        for(int i=s;i>=0;i--)
            if(grand[a][i]!=grand[b][i])
                ans+=dis[a][i]+dis[b][i],b=grand[b][i],a=grand[a][i];
        if(a!=b)
            ans+=dis[a][0]+dis[b][0];
        return ans;
    }
    int main(){
    
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            book[v]=1;
            e[u].push_back(node(v,1));
            e[v].push_back(node(u,1));
        }
        for(int i=1;i<=n;i++)
            if(!book[i]){
                root=i;
                break;
            }
    
        init();
        int m,u,v;
        scanf("%d",&m);
        scanf("%d",&u);
        int ans=0;
        for(int i=1;i<m;i++){
            scanf("%d",&v);
            ans+=LCA(u,v);
            u=v;
        }
        printf("%d
    ",ans);
        return  0;
    }
    View Code

     http://oj.fjaxyz.com:3389/problem.php?id=223
    当LCA(a,b)==a时才能参赛

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int M=1e4+4;
    struct node{
        int v;
        ll w;
        node(int vv=0,ll ww=0):v(vv),w(ww){}
    };
    vector<node>e[M];
    int grand[M][20],s,n,root,deep[M];
    ll dis[M][20],num,numt;
    void dfs(int u){
        for(int i=1;i<=s;i++){
            grand[u][i]=grand[grand[u][i-1]][i-1];
            dis[u][i]=dis[u][i-1]+dis[grand[u][i-1]][i-1];
            if(!grand[u][i])
                break;
        }
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i].v;
            if(v!=grand[u][0]){
                grand[v][0]=u;
                deep[v]=deep[u]+1;
                dis[v][0]=e[u][i].w;
                dfs(v);
            }
        }
    }
    void init(){
        s=floor(log(1.0*n)/log(2.0));
        deep[0]=-1;
        dfs(root);
    }
    void LCA(int u,int v){
        int a=u,b=v;
        if(deep[a]>deep[b])
            swap(a,b) ;
        ll ans=0;
        for(int i=s;i>=0;i--){
            if(deep[b]>deep[a]&&deep[a]<=deep[grand[b][i]])
                ans+=dis[b][i],b=grand[b][i];
        }
        for(int i=s;i>=0;i--){
            if(grand[b][i]!=grand[a][i])
                ans+=dis[b][i]+dis[a][i],a=grand[a][i],b=grand[b][i];
        }
        if(a!=b)
            ans+=dis[a][0]+dis[b][0],a=grand[a][0],b=grand[b][0];
        if(a!=u)
            return ;
      //  cout<<"!!"<<endl;
    
        numt+=ans;
        num++;
    }
    int main(){
        int m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            e[u].push_back(node(v,w));
            e[v].push_back(node(u,w));
        }
        root=1;
        init();
        while(m--){
            int u,v;
            scanf("%d%d",&u,&v);
    
            LCA(u,v);
        }
        printf("%d
    ",num);
        printf("%d
    ",numt);
    
        return 0;
    }
    View Code

     zoj 3198

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3320

    吐槽一下输出格式,言不表意!!

    题意:求用最小权值的路径连接起3个节点,问这些路径的和;

    分析,答案就是俩俩之间路径和/2;

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    const int M=5e4+4;
    struct node{
        int v,w;
        node(int vv,int ww):v(vv),w(ww){}
    };
    vector<node>e[M];
    int grand[M][20],dis[M][20],deep[M],root,s,n,book[M];
    void dfs(int u){
        for(int i=1;i<=s;i++){
            grand[u][i]=grand[grand[u][i-1]][i-1];
            dis[u][i]=dis[grand[u][i-1]][i-1]+dis[u][i-1];
            if(!grand[u][i])
                break;
        }
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i].v;
            if(v!=grand[u][0]){
                grand[v][0]=u;
                deep[v]=deep[u]+1;
                dis[v][0]=e[u][i].w;
                dfs(v);
            }
        }
    }
    void init(){
        s=floor(log(1.0*n)/log(2.0));
        deep[0]=-1;
        dfs(root);
    }
    int LCA(int a,int b){
        if(deep[a]>deep[b])
            swap(a,b);
        int ans=0;
        for(int i=s;i>=0;i--){
            if(deep[a]<deep[b]&&deep[a]<=deep[grand[b][i]])
                ans+=dis[b][i],b=grand[b][i];
        }
        for(int i=s;i>=0;i--){
            if(grand[a][i]!=grand[b][i])
                ans+=dis[a][i]+dis[b][i],a=grand[a][i],b=grand[b][i];
        }
        if(a!=b)
            ans+=dis[a][0]+dis[b][0];
        return  ans;
    }
    int main(){
        int flag=1;
        while(~scanf("%d",&n)&&n){
            if(flag)
                flag=0;
            else
                printf("
    ");
            for(int i=0;i<=n;i++){
                e[i].clear();
                deep[i]=0;
                book[i]=0;
                for(int j=0;j<=16;j++)
                    grand[i][j]=dis[i][j]=0;
    
            }
            for(int i=1;i<n;i++){
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                u++;
                v++;
                book[v]=1;
                e[u].push_back(node(v,w));
                e[v].push_back(node(u,w));
            }
            for(int i=1;i<=n;i++){
                if(!book[i]){
                    root=i;
                    break;
                }
            }
            init();
            int m;
            scanf("%d",&m);
            while(m--){
                int u,v,k;
                scanf("%d%d%d",&u,&v,&k);
                u++,v++,k++;
                int ans=0;
                ans+=LCA(u,v);
               // cout<<LCA(u,v)<<"~~~~~~~~1"<<endl;
                ans+=LCA(u,k);
               // cout<<LCA(u,k)<<"~~~~~~~~2"<<endl;
                ans+=LCA(v,k);
               // cout<<LCA(k,v)<<"~~~~~~~~3"<<endl;
                printf("%d
    ",ans/2);
            }
    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    BZOJ3752 : Hack
    XIV Open Cup named after E.V. Pankratiev. GP of SPb
    XIII Open Cup named after E.V. Pankratiev. GP of Ukraine
    BZOJ2087 : [Poi2010]Sheep
    BZOJ2080 : [Poi2010]Railway
    BZOJ2082 : [Poi2010]Divine divisor
    Moscow Pre-Finals Workshop 2016. National Taiwan U Selection
    XIII Open Cup named after E.V. Pankratiev. GP of Asia and South Caucasus
    XIII Open Cup named after E.V. Pankratiev. GP of Azov Sea
    XIII Open Cup named after E.V. Pankratiev. GP of SPb
  • 原文地址:https://www.cnblogs.com/starve/p/11200925.html
Copyright © 2011-2022 走看看