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 }
  • 相关阅读:
    &与&&的区别
    jsp之response方法
    一个数组先按照某个属性的大小排序,如果大小一样的就按照名称排序
    CSS内部div设置上min-height或max-height滚动条就会出现在父元素上
    300行代码手写简单vue.js,彻底弄懂MVVM底层原理
    JavaScript简单手写观察者模式
    javascript中replace还可以这样玩
    VUE中通过改变key去更新局部dom
    element中select的change方法如何传多个参数
    react打包中不想要sourceMap,但是在命令里加'GENERATE_SOURCEMAP=false'后windows下报错'GENERATE_SOURCEMAP' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
  • 原文地址:https://www.cnblogs.com/huangxf/p/4306317.html
Copyright © 2011-2022 走看看