zoukankan      html  css  js  c++  java
  • POJ1986 LCA在线算法

    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
    

    Hint

    Farms 2 and 6 are 20+3+13=36 apart. 

    题目大意:

    农夫约翰的牛太懒了,想走一条最短的路参加马拉松.通过POJ1984http://poj.org/problem?id=1984易知该图为无环图,因此有且仅有一条路使得路径最短,寻找最近公共祖先求解即可.

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    const int N=4e4+10;
    int head[N], ver[2*N], depth[2*N], first[N];//N个点完全遍历需要2*N-1次,注意设置数组大小为2*N
    int dir[N], dp[2*N][20];
    bool vis[N];
    int tot;
    struct edge{
        int u,v,w,next;
    }e[2*N];
    
    void add(int u,int v,int w,int &k)//构造图形
    {
        e[k].u=u,e[k].v=v,e[k].w=w;
        e[k].next=head[u],head[u]=k++;
        swap(u,v);
        e[k].u=u,e[k].v=v,e[k].w=w;
        e[k].next=head[u],head[u]=k++;
    }
    
    void dfs(int u,int dep)//深度遍历
    {
        vis[u]=1, ver[++tot]=u;
        first[u]=tot, depth[tot]=dep;
        for(int k=head[u];k!=-1;k=e[k].next)
            {
                if(!vis[e[k].v])
                    {
                        int v=e[k].v,w=e[k].w;
                        dir[v]=dir[u]+w;
                        dfs(v,dep+1);
                        ver[++tot]=u,depth[tot]=dep;
                    }
            }
    }
    
    void st(int n)
    {
        for(int i=1;i<=n;i++)
            dp[i][0]=i;//此处赋值同时储存了农场的位置
        for(int j=1;j<=20;j++)
            {
                for(int i=1;i+(1<<(j-1))-1<=n;i++)
                    {
                        int a=dp[i][j-1],b=dp[i+(1<<(j-1))][j-1];
                        depth[a]<depth[b]?dp[i][j]=a:dp[i][j]=b;//区间中深度最小的为最近公共祖先
                    }
            }
    }
    
    int rmq(int x,int y)//区间查询
    {
        int k=log2(y-x+1.0);
        int a=dp[x][k],b=dp[y-(1<<k)+1][k];
        return  depth[a]<depth[b]?a:b;
    }
    
    int LCA(int u,int v)
    {
        int x=first[u],y=first[v];//first为u,v初次出现的位置
        if(x>y) swap(x,y);
        int res=rmq(x,y);
        return ver[res];
    }
    
    int main()
    {
        int n,m,k;
        while(~scanf("%d%d",&n,&m))
            {
                int num=0;
                memset(vis,0,sizeof(vis));
                memset(head,-1,sizeof(head));
                for(int i=1;i<=m;i++)
                    {
                        int u,v,w;
                        char ch[2];
                        scanf("%d%d%d%s",&u,&v,&w,ch);
                        add(u,v,w,num);
                    }
                tot=0,dir[1]=0;
                dfs(1,1);
                st(2*n-1);
                scanf("%d",&k);
                while(k--)
                    {
                        int u,v;
                        scanf("%d%d",&u,&v);
                        int dis=LCA(u,v);
                        printf("%d
    ",dir[u]+dir[v]-2*dir[dis]);
                    }
            }
        return 0;
    }
    
  • 相关阅读:
    redis连接客户端
    map中使用的细节问题(不同key循坏中被后面的值替换)
    使用异步开启新的线程Spring异步方法注解@Async
    npm init 出现一堆提问(npm init -y)
    小程序的时间日期选择器
    小程序--分类项目跳转页面(同样也适用轮播图跳转)
    小程序样式不管用,解决方法button:not([size='mini']) { width: 184px; margin-left: auto; margin-right: auto; }
    vue-elementui的时间日期选择器( value-format="yyyy-MM-dd HH:mm:ss"),以及时间解析{y}-{m}-{d} {h}:{i}:{s}
    vue.config.js配置详细说明(逐条解释)
    element在el-table-column中如何使用过滤器
  • 原文地址:https://www.cnblogs.com/BlueDoor1999/p/13301392.html
Copyright © 2011-2022 走看看