zoukankan      html  css  js  c++  java
  • hdu 2586 How far away ? (LCA)

    http://acm.hdu.edu.cn/showproblem.php?pid=2586

      题意是给出一棵树,求两点之间的距离。

      经典LCA的题,在hdu那里无意中看到的。做法是dfs出一个先根遍历的路径,然后对路径求RMQ,当然,也可以用线段树维护。之后就是对每个询问输出dis[u]+dis[v]-dis[lca(u,v)]*2的值即可。

    代码如下:

      1 //#pragma comment(linker, "/STACK:102400000,102400000")
      2 
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 #include <vector>
      7 #include <cmath>
      8 #include <iostream>
      9 
     10 using namespace std;
     11 
     12 const int N = 111111;
     13 const int M = 44444;
     14 int rmq[18][N];
     15 
     16 void buildRMQ(int n, int *arr) {
     17     for (int i = 0; i < n; i++) rmq[0][i] = arr[i];
     18     for (int len = 1; (1 << len) <= n; len++) {
     19         for (int i = 0; i <= n - len; i++) {
     20             rmq[len][i] = min(rmq[len - 1][i], rmq[len - 1][i + (1 << len - 1)]);
     21         }
     22     }
     23 }
     24 
     25 int queryRMQ(int l, int r) {
     26     if (l > r) swap(l, r);
     27     int depth;
     28     for (depth = 0; (1 << depth + 1) <= r - l; depth++) ;
     29     return min(rmq[depth][l], rmq[depth][r - (1 << depth) + 1]);
     30 }
     31 
     32 //int test[10] = { 10, 3, 9, 5, 1, 9, 10, 11, 6, 3};
     33 //int main() {
     34 //    buildRMQ(10, test);
     35 //    for (int i = 0; i <= 4; i++) {
     36 //        for (int j = 0; j < 10; j++) {
     37 //            cout << rmq[i][j] << ' ';
     38 //        }
     39 //        cout << endl;
     40 //    }
     41 //    cout << queryRMQ(2, 5) << endl;
     42 //    cout << queryRMQ(6, 8) << endl;
     43 //    return 0;
     44 //}
     45 
     46 #define MPR make_pair
     47 #define PB push_back
     48 
     49 typedef pair<int, int> PII;
     50 vector<PII> rel[M];
     51 bool vis[M];
     52 int dis[M], path[N], id[M], pLen;
     53 
     54 void dfs(int x) {
     55     vis[x] = true;
     56     int sz = rel[x].size();
     57     path[pLen] = x;
     58     id[x] = pLen++;
     59     for (int i = 0, t; i < sz; i++) {
     60         t = rel[x][i].first;
     61         if (vis[t]) continue;
     62         dis[t] = dis[x] + rel[x][i].second;
     63         dfs(t);
     64         path[pLen++] = x;
     65     }
     66 }
     67 
     68 int query(int x, int y) {
     69     int t = queryRMQ(id[x], id[y]);
     70     return dis[x] - dis[t] + dis[y] - dis[t];
     71 }
     72 
     73 int main() {
     74 //    freopen("in", "r", stdin);
     75     int n, m, T;
     76     while (~scanf("%d", &T)) {
     77         while (T-- && ~scanf("%d%d", &n, &m)) {
     78             for (int i = 1; i <= n; i++) {
     79                 rel[i].clear();
     80                 vis[i] = false;
     81             }
     82             int x, y, c;
     83             for (int i = 1; i < n; i++) {
     84                 scanf("%d%d%d", &x, &y, &c);
     85 //                printf("%d %d %d...\n", x, y, c);
     86                 rel[x].PB(MPR(y, c));
     87                 rel[y].PB(MPR(x, c));
     88             }
     89             pLen = 0;
     90             dis[1] = 0;
     91             dfs(1);
     92 //            for (int i = 0; i < pLen; i++) cout << path[i] << ' '; cout << endl;
     93 //            for (int i = 0; i < pLen; i++) cout << dis[i] << ' '; cout << endl;
     94             buildRMQ(pLen, path);
     95             for (int i = 0; i < m; i++) {
     96                 scanf("%d%d", &x, &y);
     97                 printf("%d\n", query(x, y));
     98             }
     99         }
    100     }
    101     return 0;
    102 }
    View Code

    ——written by Lyon

  • 相关阅读:
    Linux命令 tr
    Linux命令 xargs
    Python 文件读写 文件和路径
    Python 正则表达式 匹配任意字符
    Python 正则表达式 贪心匹配和非贪心匹配
    Python 正则表达式 匹配次数
    Python 正则表达式 利用括号分组
    Python 正则表达式 search vs match
    【转-整理】 SQL2008 提示评估期已过的解决方法
    Java http接口进阶——自我理解为接口框架形式
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_2586_Lyon.html
Copyright © 2011-2022 走看看