zoukankan      html  css  js  c++  java
  • poj 1470(简单LCA 倍增法)

    题意:给你一个树,有若干个询问,然后让你统计每个结点在询问中做了几次LCA。按照结点顺序输出。

    思路:这也是简单的LCA题目,我用的是倍增法。每次查询在相应结点标记上++,最后输出即可。这道题的输入处理比较烦,而且第一个输入的结点并不是根节点。这要注意一下

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cmath>
     5 #include <cstring>
     6 #include <algorithm>
     7 #include <queue>
     8 #include <stack>
     9 #include <vector>
    10 #include <set>
    11 #include <map>
    12 #define MP(a, b) make_pair(a, b)
    13 #define PB(a) push_back(a)
    14 
    15 using namespace std;
    16 
    17 typedef long long ll;
    18 typedef pair<int ,int> pii;
    19 typedef pair<unsigned int, unsigned int> puu;
    20 typedef pair<int ,double> pid;
    21 typedef pair<ll, int> pli;
    22 
    23 const int INF = 0x3f3f3f3f;
    24 const double eps = 1e-6;
    25 const int LEN = 1000+10;
    26 const int LOG_LEN = 100;
    27 vector<int> Map[LEN];
    28 int root, parent[LOG_LEN][LEN], depth[LEN], ind[LEN];
    29 
    30 void dfs(int v, int p, int d){
    31     parent[0][v] = p;
    32     depth[v] = d;
    33     for(int i=0; i<Map[v].size(); i++){
    34         if(Map[v][i] != p) dfs(Map[v][i], v, d+1);
    35     }
    36 }
    37 
    38 void init(int n){
    39     dfs(root, -1, 0);
    40     for(int k=0; k+1<LOG_LEN; k++){
    41         for(int v=1; v<=n; v++){
    42             if(parent[k][v] < 0) parent[k+1][v] = -1;
    43             else parent[k+1][v] = parent[k][parent[k][v]];
    44         }
    45     }
    46 }
    47 
    48 int lca(int u, int v){
    49     if(depth[u] > depth[v])swap(u,v);
    50     for(int k=0; k < LOG_LEN; k++){
    51         if((depth[u] - depth[v]) >> k & 1) v = parent[k][v];
    52     }
    53     if(u==v) return u;
    54     for(int k=LOG_LEN-1; k>=0; k--){
    55         if(parent[k][v] != parent[k][u]){
    56             u = parent[k][u];
    57             v = parent[k][v];
    58         }
    59     }
    60     return parent[0][u];
    61 }
    62 
    63 int main()
    64 {
    65 //    freopen("in.txt", "r", stdin);
    66 
    67     int n, a, b, tn, q;
    68     while(scanf("%d", &n)!=EOF){
    69         for(int i=0; i<LEN; i++)Map[i].clear();
    70         memset(ind, 0, sizeof ind);
    71         for(int i=1; i<=n; i++){
    72             scanf("%d:(%d)", &a, &tn);
    73             for(int j=0; j<tn; j++){
    74                 scanf("%d", &b);
    75                 Map[a].PB(b);
    76                 Map[b].PB(a);
    77                 ind[b]++;
    78             }
    79         }
    80         for(int i=1; i<=n; i++)if(!ind[i]){root = i;break;}
    81         memset(ind, 0, sizeof ind);
    82         init(n);
    83         scanf("%d", &q);
    84         for(int i=0; i<q; i++){
    85             while(getchar() != '(');
    86             scanf("%d%d", &a, &b);
    87             while(getchar() != ')');
    88             ind[lca(a, b)] ++;
    89         }
    90         for(int i=1; i<=n; i++){
    91             if(!ind[i])continue;
    92             printf("%d:%d
    ", i, ind[i]);
    93         }
    94     }
    95     return 0;
    96 }
    View Code
    奔跑吧!少年!趁着你还年轻
  • 相关阅读:
    1062 Talent and Virtue (25 分)
    1083 List Grades (25 分)
    1149 Dangerous Goods Packaging (25 分)
    1121 Damn Single (25 分)
    1120 Friend Numbers (20 分)
    1084 Broken Keyboard (20 分)
    1092 To Buy or Not to Buy (20 分)
    数组与链表
    二叉树
    时间复杂度与空间复杂度
  • 原文地址:https://www.cnblogs.com/shu-xiaohao/p/3529693.html
Copyright © 2011-2022 走看看