可用倍增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\n",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\n",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\n",num);
    printf("%d\n",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("\n");
        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\n",ans/2);
        }

    }
    return 0;
}
View Code

 

posted @ 2019-07-17 14:40  starve_to_death  阅读(123)  评论(0编辑  收藏  举报