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
  • 相关阅读:
    在python中处理XML
    正则表达式
    python 反射
    python模块概况,json/pickle,time/datetime,logging
    python装饰器
    python3内置函数详解
    python函数,lambda表达式,三目运算,列表解析,递归
    python数据类型及其常用方法
    python3的文件操作
    初识Docker
  • 原文地址:https://www.cnblogs.com/starve/p/11200925.html
Copyright © 2011-2022 走看看