zoukankan      html  css  js  c++  java
  • poj 1986 Distance Queries LCA

    题目链接:http://poj.org/problem?id=1986

    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! 

    题目描述:已知n(n<=40000)个农场和一些农场之间的距离,给出很多组询问,在线询问每两个农场之间的距离。

    算法分析:这道题运用LCA的在线和离线算法都可以。

    离线LCA思路:以某一个农场为树根,用数组保存剩余每个农场到树根的距离为dist[u],那么农场u和v的距离=dist[u]+dist[v]-2*dist[q](q为LCA(u,v))。

    我的做法虽然可以AC,但是很慢,有很大的优化空间:在两个节点不断向树根靠近的同时,把每向上走一层的路径上的权值(即农场之间的距离)加起来即为答案。我用离线的LCA代码运用在在线方法上,仔细想想在求每个节点的深度时就可以把离线思想中dist数组求出来了,更简单,速度更快。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<cmath>
      6 #include<algorithm>
      7 #include<vector>
      8 #define inf 0x7fffffff
      9 using namespace std;
     10 const int maxn=40000+10;
     11 const int max_log_maxn=16;
     12 
     13 int n,m,root;
     14 vector<pair<int,int> > G[maxn];
     15 int father[max_log_maxn][maxn],d[maxn];
     16 int sum[max_log_maxn][maxn];
     17 
     18 void dfs(int u,int p,int depth)
     19 {
     20     father[0][u]=p;
     21     d[u]=depth;
     22     int num=G[u].size();
     23     for (int i=0 ;i<num ;i++)
     24     {
     25         int v=G[u][i].first;
     26         int len=G[u][i].second;
     27         if (v != p)
     28         {
     29             sum[0][v]=len;
     30             dfs(v,u,depth+1);
     31         }
     32     }
     33 }
     34 
     35 void init()
     36 {
     37     dfs(root,-1,0);
     38     for (int k=0 ;k+1<max_log_maxn ;k++)
     39     {
     40         for (int i=1 ;i<=n ;i++)
     41         {
     42             if (father[k][i]<0)
     43             {
     44                 father[k+1][i]=-1;
     45                 sum[k+1][i]=0;
     46             }
     47             else
     48             {
     49                 father[k+1][i]=father[k][father[k][i] ];
     50                 sum[k+1][i]=sum[k][i]+sum[k][father[k][i] ];
     51             }
     52         }
     53     }
     54 }
     55 
     56 int LCA(int u,int v)
     57 {
     58     if (d[u]>d[v]) swap(u,v);
     59     int Sum=0;
     60     for (int k=0 ;k<max_log_maxn ;k++)
     61     {
     62         if ((d[v]-d[u])>>k & 1)
     63         {
     64             Sum += sum[k][v];
     65             v=father[k][v];
     66         }
     67     }
     68     if (u==v) return Sum;
     69     for (int k=max_log_maxn-1 ;k>=0 ;k--)
     70     {
     71         if (father[k][u] != father[k][v])
     72         {
     73             Sum += sum[k][u];
     74             Sum += sum[k][v];
     75             u=father[k][u];
     76             v=father[k][v];
     77         }
     78     }
     79     Sum += sum[0][u];
     80     Sum += sum[0][v];
     81     return Sum;
     82 }
     83 
     84 int main()
     85 {
     86     while (scanf("%d%d",&n,&m)!=EOF)
     87     {
     88         int u,v,length;
     89         char ch[2];
     90         for (int i=0 ;i<=n ;i++) G[i].clear();
     91         for (int i=0 ;i<max_log_maxn ;i++)
     92         {
     93             for (int j=0 ;j<maxn ;j++)
     94                 sum[i][j]=0;
     95         }
     96         for (int i=0 ;i<m ;i++)
     97         {
     98             scanf("%d%d%d%s",&u,&v,&length,ch);
     99             G[u].push_back(make_pair(v,length));
    100             G[v].push_back(make_pair(u,length));
    101         }
    102         root=1;
    103         init();
    104         int k;
    105         scanf("%d",&k);
    106         for (int i=0 ;i<k ;i++)
    107         {
    108             scanf("%d%d",&u,&v);
    109             printf("%d
    ",LCA(u,v));
    110         }
    111     }
    112     return 0;
    113 }
  • 相关阅读:
    Python语言基础03-分支和循环结构
    Python语言基础01-初识Python
    李宏毅深度学习笔记08---Bert、ELMO、GPT
    李宏毅深度学习笔记07---Transformer
    李宏毅深度学习笔记06---word embedding(词嵌入也称词向量)
    李宏毅深度学习笔记05---RNN 循环神经网络02
    李宏毅深度学习笔记04---RNN 循环神经网络01
    李宏毅深度学习笔记03---CNN 卷积神经网络
    李宏毅深度学习笔记02---深度学习的发展历程、3大研究步骤、
    李宏毅深度学习笔记---课程介绍
  • 原文地址:https://www.cnblogs.com/huangxf/p/4306317.html
Copyright © 2011-2022 走看看