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 }
  • 相关阅读:
    wireshark无法捕获无线网卡数据解决办法(failed to set hardware filter to promiscuous mode)
    用PHP检测用户是用手机(Mobile)还是电脑(PC)访问网站
    一次.net Socket UDP编程的10万客户端测试记录
    对象复制
    c#中volatile关键字的作用
    C#操作XML
    ASP.NET AJAX
    C#操作XMl2
    SQLServer 存储过程中不拼接SQL字符串实现多条件查询
    ASP.NET刷新页面的六种方法20081111 22:04asp.net页面刷新重是有问题,收藏几种方法挺有用的.
  • 原文地址:https://www.cnblogs.com/huangxf/p/4306317.html
Copyright © 2011-2022 走看看