zoukankan      html  css  js  c++  java
  • Distance Queries 距离咨询 (LCA倍增模板)

    农夫约翰有N(2<=N<=40000)个农场,标号1到N。M(2<=M<=40000)条的不同的垂直或水平的道路连结着农场,道路的长度不超过1000.这些农场的分布就像下面的地图一样,图中农场用F1..F7表示:

    image

    每个农场最多能在东西南北四个方向连结4个不同的农场。此外,农场只处在道路的两端。道路不会交叉而且每对农场间有且仅有一条路径。邻居鲍伯要约翰来导航,但约翰丢了农场的地图,他只得从电脑的备份中修复率。每一条道路的信息如下:

        从农场23往南经距离10到达农场17
    
    从农场1往东经距离7到达农场17
    
    . . .
    

    最近美国过度肥胖非常普遍。农夫约翰为了让他的奶牛多做运动,举办了奶牛马拉松。马拉松路线要尽量长。

    奶牛们拒绝跑马拉松,因为她们悠闲的生活无法承受约翰选择的如此长的赛道。因此约翰决心找一条更合理的赛道。他打算咨询你。读入地图之后会有K个问题,每个问题包括2个整数,就是约翰感兴趣的2个农场的编号,请尽快算出这2个农场间的距离。

    输入格式

    第1行:两个分开的整数N和M。

    第2到M+1行:每行包括4个分开的内容,F1,F2,L,D分别描述两个农场的编号,道路的长度,F1到F2的方向N,E,S,W。

    第2+M行:一个整数K(1<=K<=10000).

    第3+M到2+M+K行:每行输入2个整数,代表2个农场。

    输出格式

    对每个问题,输出单独的一个整数,给出正确的距离。

    样例

    样例输入

    7 6
    1 6 13 E
    6 3 9 E
    3 5 7 S
    4 1 3 N
    2 4 20 W
    4 7 2 S
    3
    1 6
    1 4
    2 6
    

    样例输出

    13
    3
    36
    

    样例解释

    农场2到农场6有20+3+13=36的距离


    析:LCA模板先将 x与y翻到同一深度,然后继续上翻,利用二进制


    代码如下:

    #include<bits/stdc++.h>
    #define ll long long
    #define re register int
    #define N 500100
    using namespace std;
    ll sum[N],fa[N][30],p[N][30];
    ll to[N<<1],next[N<<1],head[N<<1],w[N<<1];
    ll deep[N],dis[N];
    ll n,m,k,tot;
    ll a,b,c;
    char ch[5];
    void add(ll x,ll y,ll z)
    {
        to[++tot]=y;
        next[tot]=head[x];
        head[x]=tot;
        w[tot]=z;
    }
    void bfs(ll x,ll f)
    {
        for(re i=1;(1<<i)<=n;i++)
            fa[x][i]=fa[fa[x][i-1]][i-1];
        for(re i=head[x];i;i=next[i])
        {
            ll p=to[i];
            if(p==f)
                continue;
            deep[p]=deep[x]+1;
            dis[p]=dis[x]+w[i];
            fa[p][0]=x;
            bfs(p,x);
        }
    }
    ll lca(ll x,ll y)
    {
        if(deep[x]<deep[y])
            return lca(y,x);
        ll d=deep[x]-deep[y];
        for(re i=0;(1<<i)<=d;i++)
            if((1<<i)&d)
                x=fa[x][i];
        if(x==y)
            return x;
        for(re i=18;i>=0;i--)
            if(fa[x][i]!=fa[y][i])
            {
                x=fa[x][i];
                y=fa[y][i];
            }
        return fa[x][0];
    }
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for(re i=1;i<=m;i++)
        {
            scanf("%lld%lld%lld%s",&a,&b,&c,ch);
            add(a,b,c);
            add(b,a,c);
        }
        bfs(1,0);
        scanf("%lld",&k);
        while(k--)
        {
            scanf("%lld%lld",&a,&b);
            //cout<<"dis[a]="<<dis[a]<<" dis[b]="<<dis[b]<<" dis[lca]="<<dis[lca(a,b)]<<" lca="<<lca(a,b)<<endl;
            printf("%lld\n",dis[a]+dis[b]-2*dis[lca(a,b)]);
        }
        return 0;
    }

  • 相关阅读:
    739. Daily Temperatures
    556. Next Greater Element III
    1078. Occurrences After Bigram
    1053. Previous Permutation With One Swap
    565. Array Nesting
    1052. Grumpy Bookstore Owner
    1051. Height Checker
    数据库入门及SQL基本语法
    ISCSI的概念
    配置一个IP SAN 存储服务器
  • 原文地址:https://www.cnblogs.com/WindZR/p/14672839.html
Copyright © 2011-2022 走看看