• POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 【USACO】距离咨询(最近公共祖先)


    POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 【USACO】距离咨询(最近公共祖先)

    Description

    Farmer John's cows refused to run in his marathon since he chose a path much too long for their leisurely lifestyle. He therefore wants to find a path of a more reasonable length. The input to this problem consists of the same input as in "Navigation Nightmare",followed by a line containing a single integer K, followed by K "distance queries". Each distance query is a line of input containing two integers, giving the numbers of two farms between which FJ is interested in computing distance (measured in the length of the roads along the path between the two farms). Please answer FJ's distance queries as quickly as possible!

    Input

    Lines 1..1+M: Same format as "Navigation Nightmare"

    Line 2+M: A single integer, K. 1 <= K <= 10,000

    Lines 3+M..2+M+K: Each line corresponds to a distance query and contains the indices of two farms.

    Output

    Lines 1..K: For each distance query, output on a single line an integer giving the appropriate distance.

    Sample Input

    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

    Sample Output

    13
    3
    36

    Http

    POJ:https://vjudge.net/problem/POJ-1986
    UESTC:https://vjudge.net/problem/UESTC-256

    Source

    最近公共祖先LCA

    题目大意

    在一棵边带权的树上回答若干个两点之间距离的询问

    解决思路

    这题当然是用floyed解啦
    (以上纯属胡扯)
    在树上求两点之间的距离何必用Floyed呢?我们有LCA。

    那么如何用LCA解这道题呢?关于LCA倍增算法的基本思路请参照我的这篇文章

    但上文讲述的是边不带权的情况,本题中,我们要做一些改变。

    首先,为了方便起见,我们设根节点为1号点,那么Depth和Parent的定义都没有变,我们再加上一个Dist[u]表示u到1的距离(注意和Depth的区别,一个是深度,记录节点数,另一个是距离,记录边权和)

    那么两个点之间的距离就是Dist[u]+Dist[v]-2*Dist[LCA(u,v)]啦。
    简单解释一下,设u和v的最近公共祖先为p,u和v的距离首先可以是u到p的距离+v到p的距离,而u到p的距离又可以是Dist[u]-Dist[p],v也同理,所以两式相加就可以得到上面的式子了。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    
    class Edge
    {
    public:
        int v,w;
    };
    
    const int maxN=210000;
    const int inf=2147483647;
    
    int n,m;
    vector<Edge> E[maxN];
    int Depth[maxN];
    int Dist[maxN];
    int Parent[maxN][23];
    bool vis[maxN];
    
    void LCA_init();
    void dfs(int u);
    int LCA(int a,int b);
    
    int main()
    {
        cin>>n>>m;
        for (int i=1;i<=m;i++)
        {
            int a,b,c;
            char ch;
            scanf("%d%d%d",&a,&b,&c);
            cin>>ch;
            E[a].push_back((Edge){b,c});
            E[b].push_back((Edge){a,c});
        }
        LCA_init();
        int Q;
        scanf("%d",&Q);
        for (int i=1;i<=Q;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            cout<<Dist[u]+Dist[v]-2*Dist[LCA(u,v)]<<endl;
        }
        return 0;
    }
    
    void LCA_init()
    {
        memset(Dist,0,sizeof(Dist));
        memset(Parent,0,sizeof(Parent));
        memset(Depth,0,sizeof(Depth));
        memset(vis,0,sizeof(vis));
        dfs(1);
        for (int j=1;j<=20;j++)
            for (int i=1;i<=n;i++)
                Parent[i][j]=Parent[Parent[i][j-1]][j-1];
        return;
    }
    
    void dfs(int u)
    {
        vis[u]=1;
        for (int i=0;i<E[u].size();i++)
        {
            int v=E[u][i].v;
            if (vis[v]==0)
            {
                Depth[v]=Depth[u]+1;
                Dist[v]=Dist[u]+E[u][i].w;
                Parent[v][0]=u;
                dfs(v);
            }
        }
        return;
    }
    
    int LCA(int a,int b)
    {
        if (Depth[a]<Depth[b])
            swap(a,b);
        for (int i=20;i>=0;i--)
            if ((Parent[a][i]!=0)&&(Depth[Parent[a][i]]>=Depth[b]))
                a=Parent[a][i];
        if (a==b)
            return a;
        for (int i=20;i>=0;i--)
            if ((Parent[a][i]!=0)&&(Parent[b][i]!=0)&&(Parent[a][i]!=Parent[b][i]))
            {
                a=Parent[a][i];
                b=Parent[b][i];
            }
        return Parent[a][0];
    }
    
  • 相关阅读:
    第一个程序01 零基础入门学习汇编语言20
    函数03 零基础入门学习C语言34
    函数03 零基础入门学习C语言34
    寄存器(内存访问)05 零基础入门学习汇编语言17
    寄存器(内存访问)06 零基础入门学习汇编语言18
    寄存器(内存访问)07 零基础入门学习汇编语言19
    寄存器(内存访问)06 零基础入门学习汇编语言18
    VC++实现恢复SSDT
    现实世界Windows Azure: 排气系统制造商 Akrapovič Revs 运用Windows Azure进行全球运营
    VC++实现全局钩子勾住消息对话框
  • 原文地址:https://www.cnblogs.com/SYCstudio/p/7150606.html
Copyright © 2020-2023  润新知