hdu 4547 (LCA 倍增法)

中文题就不解释了。

简单LCA,就是求第一个点到LCA的距离,在判断第二个点是不是LCA,不是答案再加一就可。至于求距离的话直接利用倍增法的parent数组拆成二进制复杂度为logn。

代码如下:

  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 map<string, int> mp;
 29 int ind[LEN], n ,m, root, depth[LEN], parent[LOG_LEN][LEN];
 30 
 31 void dfs(int v, int p, int d){
 32     parent[0][v] = p;
 33     depth[v] = d;
 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=0; 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     int ret = 0;
 53     if(depth[u]>depth[v])swap(u, v);
 54     for(int k=0; k<LOG_LEN; k++){
 55         if((depth[v]-depth[u]) >> k & 1) v = parent[k][v];
 56     }
 57     if(u==v) return u;
 58     for(int k=LOG_LEN-1; k>=0; k--){
 59         if(parent[k][u]!=parent[k][v]){
 60             u = parent[k][u];
 61             v = parent[k][v];
 62         }
 63     }
 64     return parent[0][v];
 65 }
 66 
 67 int solve(int v, int p){
 68     int ret = 0;
 69     for(int i=LOG_LEN-1; i>=0; i--)
 70         if(parent[i][v]!=-1 && depth[parent[i][v]]>=depth[p]){
 71             v = parent[i][v];
 72             ret+=(1<<i);
 73         }
 74     return ret;
 75 }
 76 
 77 int main()
 78 {
 79 //    freopen("in.txt", "r", stdin);
 80 
 81     int T, a, b;
 82     char va[110], vb[110];
 83     scanf("%d", &T);
 84     while(T--){
 85         for(int i=0; i<LEN; i++)Map[i].clear();
 86         mp.clear();
 87         memset(ind, 0, sizeof ind);
 88         scanf("%d%d", &n, &m);
 89         int vcnt = 0;
 90         for(int i=0; i<n-1; i++){
 91             scanf("%s%s", va, vb);
 92             if(!mp.count(va)) mp[va] = vcnt++;
 93             if(!mp.count(vb)) mp[vb] = vcnt++;
 94             ind[mp[va]] ++;
 95             Map[mp[va]].PB(mp[vb]);
 96             Map[mp[vb]].PB(mp[va]);
 97         }
 98         for(int i=0; i<n; i++)if(!ind[i]){root = i;break;}
 99         init(n);
100         for(int i=0; i<m; i++){
101             scanf("%s%s", va, vb);
102             int lv = lca(mp[va], mp[vb]);
103             printf("%d
", solve(mp[va], lv)+(lv==mp[vb]?0:1));
104         }
105     }
106     return 0;
107 }
View Code
奔跑吧!少年!趁着你还年轻
原文地址:https://www.cnblogs.com/shu-xiaohao/p/3529904.html