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 }
  • 相关阅读:
    [HNOI2007]最小矩形覆盖
    Java实现第十届蓝桥杯质数
    Redo current损坏
    [学习笔记]计算几何
    delete noprompt archivelog 报错ORA-00245,RMAN-08132
    [学习笔记]CDQ分治
    Java实现第九届蓝桥杯耐摔指数
    RAC RMAN 备份 RMAN-03009 ORA-19504 ORA-27040 RMAN-06012 channel c3 not allocated 错误分析
    [学习笔记]树套树
    RMAN-03002、RMAN-06059
  • 原文地址:https://www.cnblogs.com/huangxf/p/4306317.html
Copyright © 2011-2022 走看看