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;
    }
    
  • 相关阅读:
    【NOIP2016提高组】 Day1 T3 换教室
    【NOIP2016 Day1 T2】天天爱跑步
    web@前端--html,css,javascript简介、第一个页面(常用标签简介)
    MySQL--视图view、触发器trigger、事务(start transaction)、存储过程(特殊的数据逻辑处理函数)、流程控制(if,case....)
    MySQL--pymysql模块
    MySQL--(了解)可能会用到的内置函数
    MySQL--详细查询操作(单表记录查询、多表记录查询(连表查询)、子查询)
    MySQL--表操作(约束条件foreign key关联表 多对1,多对多,1对1)
    MySQL--表操作(innodb表字段数据类型、约束条件)、sql_mode操作
    MySQL基本语句、存储引擎
  • 原文地址:https://www.cnblogs.com/BlueDoor1999/p/13301392.html
Copyright © 2011-2022 走看看