zoukankan      html  css  js  c++  java
  • 算法笔记--lca倍增算法

    算法笔记

    模板:

    vector<int>g[N];
    vector<int>edge[N];
    int anc[20][N];
    int deep[N];
    int h[N];
    void dfs(int o,int u,int w)
    {
        if(u!=o)deep[u]=deep[o]+1,h[u]=h[o]+w;
        for(int j=0;j<g[u].size();j++)
        {
            if(g[u][j]!=o)
            {
                anc[0][g[u][j]]=u;
                for(int i=1;i<20;i++)anc[i][g[u][j]]=anc[i-1][anc[i-1][g[u][j]]];
                dfs(u,g[u][j],edge[u][j]);
            }
        }
    }
    int lca(int u,int v)
    {
        if(deep[u]<deep[v])swap(u,v);
        for(int i=19;i>=0;i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u];
        if(u==v)return u;
        for(int i=19;i>=0;i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
        return anc[0][u];
    } 
    int dis(int u,int v)
    {
        int l=lca(u,v);
        return h[u]+h[v]-2*h[l];
    }
    View Code

    例题:

    1.CODEVS 2370 小机房的树

    带权lca

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    const int INF=0x3f3f3f3f;
    const int N=5e4+5;
    vector<int>g[N];
    vector<int>edge[N];
    int anc[20][N];
    int deep[N];
    int h[N];
    void dfs(int o,int u,int w)
    {
        if(u!=o)deep[u]=deep[o]+1,h[u]=h[o]+w;
        for(int j=0;j<g[u].size();j++)
        {
            if(g[u][j]!=o)
            {
                anc[0][g[u][j]]=u;
                for(int i=1;i<20;i++)anc[i][g[u][j]]=anc[i-1][anc[i-1][g[u][j]]];
                dfs(u,g[u][j],edge[u][j]);
            }
        }
    }
    int lca(int u,int v)
    {
        if(deep[u]<deep[v])swap(u,v);
        for(int i=19;i>=0;i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u];
        if(u==v)return u;
        for(int i=19;i>=0;i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
        return anc[0][u];
    } 
    int dis(int u,int v)
    {
        int l=lca(u,v);
        return h[u]+h[v]-2*h[l];
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,u,v,c,m;
        cin>>n;
        for(int i=0;i<n-1;i++)
        {
            cin>>u>>v>>c;
            g[u].push_back(v);
            g[v].push_back(u);
            edge[u].push_back(c);
            edge[v].push_back(c);
        }
        cin>>m;
        for(int i=0;i<20;i++)anc[i][0]=0;
        dfs(0,0,0);
        while(m--)
        {
            cin>>u>>v;
            cout<<dis(u,v)<<endl;
        }
        return 0;
    }
    View Code

    2.CODEVS 1036 商务旅行

    普通lca

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define ls rt<<1,l,m
    #define rs rt<<1|1,m+1,r
    const int INF=0x3f3f3f3f;
    const int N=1e5+5;
    vector<int>g[N];
    int anc[20][N];
    int deep[N];
    void dfs(int o,int u)
    {
        if(o!=u)deep[u]=deep[o]+1;
        for(int j=0;j<g[u].size();j++)
        {
            if(o!=g[u][j])
            {
                anc[0][g[u][j]]=u;
                for(int i=1;i<20;i++)anc[i][g[u][j]]=anc[i-1][anc[i-1][g[u][j]]];
                dfs(u,g[u][j]);
            }
        }
    }
    int lca(int u,int v)
    {
        if(deep[u]<deep[v])swap(u,v);
        for(int i=19;i>=0;i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u];
        if(u==v)return u;
        for(int i=19;i>=0;i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
        return anc[0][u];
    } 
    int dis(int u,int v)
    {
        return deep[u]+deep[v]-2*deep[lca(u,v)];
    }
    void init()
    {
        for(int i=0;i<20;i++)anc[0][1]=1;
        dfs(0,1);
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,m;
        cin>>n;
        for(int i=1;i<n;i++)
        {
            int a,b;
            cin>>a>>b;
            g[a].push_back(b);
            g[b].push_back(a);
        }
        init();
        cin>>m;
        int a,b,ans=0;
        cin>>a;
        for(int i=1;i<m;i++)
        {
            cin>>b;
            ans+=dis(a,b);
            a=b;
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

    3.METO CODE P223 拉力赛

    带权lca,当lca(a,b)==a时,韵韵才能参加。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define ls rt<<1,l,m
    #define rs rt<<1|1,m+1,r
    #define pb push_back
    const int INF=0x3f3f3f3f;
    const int N=1e4+5;
    vector<int>g[N];
    vector<ll>edge[N];
    int anc[20][N];
    int deep[N];
    ll h[N];
    bool vis[N]={false};
    int s;
    void dfs(int o,int u,ll w)
    {
        if(o!=u)deep[u]=deep[o]+1,h[u]=h[o]+w;
        for(int j=0;j<g[u].size();j++)
        {
            if(g[u][j]!=o)
            {
                anc[0][g[u][j]]=u;
                for(int i=1;i<20;i++)anc[i][g[u][j]]=anc[i-1][anc[i-1][g[u][j]]];
                dfs(u,g[u][j],edge[u][j]);
            }
        }
    }
    int lca(int u,int v)
    {
        if(deep[u]<deep[v])swap(u,v);
        for(int i=19;i>=0;i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u];
        if(u==v)return u;
        for(int i=19;i>=0;i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
        return anc[0][u];
    }
    ll dis(int u,int v)
    {
        return h[u]+h[v]-2*h[lca(u,v)];
    }
    void init()
    {
        for(int i=0;i<20;i++)anc[i][1]=1;
        dfs(0,1,1);
    } 
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,m,a,b;
        ll t;
        cin>>n>>m;
        for(int i=1;i<n;i++)
        {
            cin>>a>>b>>t;
            g[a].pb(b);
            g[b].pb(a);
            edge[a].pb(t);
            edge[b].pb(t);
        }
        init();
        int cnt=0;
        ll ans=0;
        for(int i=0;i<m;i++)
        {
            int a,b;
            cin>>a>>b;
            if(lca(a,b)==a)
            {
                cnt++;
                ans+=h[b]-h[a];
            }
            }
        cout<<cnt<<endl;
        cout<<ans<<endl;
        return 0;
    }
    View Code

    4.HDU 2586 How far way?

    带权lca

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    const int INF=0x3f3f3f3f;
    const int N=4e4+5;
    vector<int>g[N];
    vector<int>edge[N];
    int deep[N];
    int h[N];
    int anc[20][N];
    bool vis[N]={false};
    int s=1;
    void dfs(int o,int u,int w)
    {
        deep[u]=deep[o]+1;
        h[u]=h[o]+w;
        for(int j=0;j<g[u].size();j++)
        {
            if(g[u][j]!=o)
            {
                anc[0][g[u][j]]=u;
                for(int i=1;i<20;i++)anc[i][g[u][j]]=anc[i-1][anc[i-1][g[u][j]]];
                dfs(u,g[u][j],edge[u][j]);
            }
        }
    }
    int lca(int u,int v)
    {
        if(deep[u]<deep[v])swap(u,v);
        for(int i=19;i>=0;i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u];
        if(u==v)return u;
        for(int i=19;i>=0;i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
        return anc[0][u];
    } 
    ll dis(int u,int v)
    {
        return h[u]+h[v]-2*h[lca(u,v)];
    }
    void init()
    {
        for(int i=0;i<20;i++)anc[i][1]=1;
        dfs(0,1,1);
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t;
        cin>>t;
        while(t--)
        {
            int n,m,a,b,k;
            cin>>n>>m;
            for(int i=1;i<n;i++)
            {
                cin>>a>>b>>k;
                g[a].pb(b);
                g[b].pb(a);
                edge[a].pb(k);
                edge[b].pb(k);
                vis[b]=true;
            }
            init();
            for(int i=0;i<m;i++)
            {
                cin>>a>>b;
                cout<<dis(a,b)<<endl;
            }
            //cout<<endl;
        }
        return 0;
    }
    View Code

    5.ZOJ P3195 Design the city

    带权lca,三点之间的最短路径公式h[a]+h[b]+h[c]-h[lca(a,b)]-h[lca(a,c)]-h[lca(b,c)]。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define pb push_back
    const int INF=0x3f3f3f3f;
    const int N=5e4+5;
    vector<int>g[N];
    vector<int>edge[N];
    int deep[N];
    int h[N];
    int anc[20][N];
    void dfs(int o,int u,int w)
    {
        if(u!=o)deep[u]=deep[o]+1,h[u]=h[o]+w;
        for(int j=0;j<g[u].size();j++)
        {
            if(g[u][j]!=o)
            {
                anc[0][g[u][j]]=u;
                for(int i=1;i<20;i++)anc[i][g[u][j]]=anc[i-1][anc[i-1][g[u][j]]];
                dfs(u,g[u][j],edge[u][j]);
            }
        }
    }
    int lca(int u,int v)
    {
        if(deep[u]<deep[v])swap(u,v);
        for(int i=19;i>=0;i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u];
        if(u==v)return u;
        for(int i=19;i>=0;i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
        return anc[0][u];
    }
    int dis(int u,int v)
    {
        return h[u]+h[v]-2*h[lca(u,v)];
    }
    void init()
    {
        for(int i=0;i<20;i++)anc[i][0]=0;
        dfs(0,0,0);
    }
    int main()
    {
        int n,q,a,b,c;
        bool flag=true;
        while(~scanf("%d",&n)&&n)
        {
            if(flag) flag=false;
            else printf("
    ");
            for(int i=0;i<n;i++)g[i].clear(),edge[i].clear();
            for(int i=1;i<n;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                g[a].pb(b);
                g[b].pb(a);
                edge[a].pb(c);
                edge[b].pb(c);
            }
            init();
            scanf("%d",&q);
            while(q--)
            {
                scanf("%d%d%d",&a,&b,&c);
                printf("%d
    ",h[a]+h[b]+h[c]-h[lca(a,b)]-h[lca(a,c)]-h[lca(b,c)]);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    gcc -I -L -l区别
    如何在LINUX中开机、登陆、退出、定时、定期自动运行程序
    4B/5B编码原理
    powerpc平台移植zebra或quagga-0.99.23
    ubuntu 命令配置ip 网关 dns
    ubuntu新机安装工具
    svn add --no-ignore
    SSL handshake failed: SSL error: Key usage violation in certificate has been detected.
    netif_start_queue/netif_wake_queue/netif_stop_queue
    Linux系统中提示/usr/bin/ld: cannot find -lxxx错误的通用解决方法
  • 原文地址:https://www.cnblogs.com/widsom/p/7259161.html
Copyright © 2011-2022 走看看