zoukankan      html  css  js  c++  java
  • poj 1330 (简单LCA 暴力法 / 倍增法)

    题意:现实给你一棵树然后给你树上的n-1条边,接着给你一对顶点,然后让你求这对顶点的LCA。

    思路:由于刚刚学习LCA所以找了这一道最最水的LCA题目来做发现用复杂度较高的算法也能过,就是先遍历求出每个结点的父亲和深度,然后再将深度深的向上走,一直走到两个结点在同一高度上。再两个节点一起往上走,直到走到一个节点那么这个节点即为那两个节点的LCA。

    暴力法代码如下:

     1 //LCA
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstdlib>
     5 #include <cmath>
     6 #include <cstring>
     7 #include <algorithm>
     8 #include <queue>
     9 #include <stack>
    10 #include <vector>
    11 #include <set>
    12 #include <map>
    13 #define MP(a, b) make_pair(a, b)
    14 #define PB(a) push_back(a)
    15 
    16 using namespace std;
    17 
    18 typedef long long ll;
    19 typedef pair<int ,int> pii;
    20 typedef pair<unsigned int, unsigned int> puu;
    21 typedef pair<int ,double> pid;
    22 typedef pair<ll, int> pli;
    23 
    24 const int INF = 0x3f3f3f3f;
    25 const double eps = 1e-6;
    26 const int LEN = 100000+10;
    27 vector<int> Map[LEN];
    28 int root, ind[LEN], depth[LEN], parent[LEN];
    29 
    30 void dfs(int v, int p, int d){
    31     parent[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() {dfs(root, -1, 0);}
    39 
    40 int lca(int u, int v){
    41     while(depth[u] > depth[v]) u = parent[u];
    42     while(depth[v] > depth[u]) v = parent[v];
    43     while(u!=v){
    44         u = parent[u];
    45         v = parent[v];
    46     }
    47     return u;
    48 }
    49 
    50 int main()
    51 {
    52 //    freopen("in.txt", "r", stdin);
    53 
    54     int n, a, b, T;
    55     scanf("%d", &T);
    56     while(T--){
    57         for(int i=0; i<LEN; i++)Map[i].clear();
    58         memset(ind, 0, sizeof ind);
    59         scanf("%d", &n);
    60         for(int i=0; i<n-1; i++){
    61             scanf("%d%d", &a, &b);
    62             Map[a].PB(b);
    63             Map[b].PB(a);
    64             ind[b]++;
    65         }
    66         for(int i=1; i<=n; i++)
    67             if(ind[i]==0) {root = i;break;}
    68         init();
    69         scanf("%d%d", &a, &b);
    70         int ans = lca(a, b);
    71         printf("%d
    ", ans);
    72     }
    73     return 0;
    74 }
    View Code

    倍增法代码如下:

     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 = 100010;
    26 const int LOG_LEN = 22;
    27 vector<int> Map[LEN];
    28 int ind[LEN], root, parent[LOG_LEN][LEN], depth[LEN];
    29 
    30 void dfs(int v, int p, int d)
    31 {
    32     depth[v] = d;
    33     parent[0][v] = p;
    34     for(int i=0; i<Map[v].size(); i++){
    35         if(Map[v][i]!=p) dfs(Map[v][i], v, d+1);
    36     }
    37 }
    38 
    39 void init(int n)
    40 {
    41     dfs(root, -1, 0);
    42     for(int k=0; k+1<LOG_LEN; k++){
    43         for(int i=1; i<=n; i++){
    44             if(parent[k][i] < 0) parent[k+1][i] = -1;
    45             else parent[k+1][i] = parent[k][parent[k][i]];
    46         }
    47     }
    48 }
    49 
    50 int lca(int u, int v)
    51 {
    52     if(depth[u] > depth[v]) swap(u, v);
    53     for(int i=0; i<LOG_LEN; i++){
    54         if((depth[v]-depth[u]) >> i & 1) v = parent[i][v];
    55     }
    56     if(u==v) return u;
    57     for(int i=LOG_LEN-1; i>=0; i--){
    58         if(parent[i][u]!=parent[i][v]){
    59             v = parent[i][v];
    60             u = parent[i][u];
    61         }
    62     }
    63     return parent[0][u];
    64 }
    65 
    66 int main()
    67 {
    68 //    freopen("in.txt", "r", stdin);
    69 
    70     int T, n, a, b;
    71     scanf("%d", &T);
    72     while(T--){
    73         scanf("%d", &n);
    74         memset(ind, 0, sizeof ind);
    75         for(int i=0; i<LEN; i++)Map[i].clear();
    76         for(int i=0; i<n-1; i++){
    77             scanf("%d%d", &a, &b);
    78             Map[a].PB(b);
    79             Map[b].PB(a);
    80             ind[b]++;
    81         }
    82         for(int i=1; i<=n; i++)if(!ind[i]){root = i;break;}
    83         init(n);
    84         scanf("%d%d", &a, &b);
    85         printf("%d
    ", lca(a, b));
    86     }
    87     return 0;
    88 }
    View Code
    奔跑吧!少年!趁着你还年轻
  • 相关阅读:
    java并发:简单面试问题集锦
    Java:泛型
    Java:注解(元数据)
    Java:反射
    Java:静态代理 and 动态代理
    华为机试题——该警醒了,骚年
    java并发:线程同步机制之Lock
    java并发:中断一个正在运行的线程
    java中String类型变量的赋值问题
    java中的自增问题
  • 原文地址:https://www.cnblogs.com/shu-xiaohao/p/3529591.html
Copyright © 2011-2022 走看看