POJ 1330(LCA/倍增法模板)
链接:http://poj.org/problem?id=1330
题意:q次询问求两个点u,v的LCA
思路:LCA模板题,首先找一下树的根,然后dfs预处理求LCA(u,v)
AC代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 #include<set> 6 #include<string> 7 #include<vector> 8 #include<stack> 9 #include<queue> 10 using namespace std; 11 typedef long long ll; 12 const int maxbit = 15; 13 const int maxn = 1e4+5; 14 vector<int> G[maxn]; 15 int depth[maxn]; 16 int fa[maxn][maxbit]; 17 int Log[maxn]; 18 int N; 19 void pre(){ 20 Log[0] = -1; 21 Log[1] = 0,Log[2] = 1; 22 for(int i = 3;i<maxn;i++) Log[i] = Log[i/2] + 1; 23 } 24 void dfs(int cur,int father){//dfs预处理 25 depth[cur] = depth[father] + 1;//当前结点的深度为父亲结点+1 26 fa[cur][0] = father;//更新当前结点的父亲结点 27 for(int j = 1;(1<<j)<=N;j++){//倍增更新当前结点的祖先 28 fa[cur][j] = fa[fa[cur][j-1]][j-1]; 29 } 30 for(int i = 0;i<G[cur].size() ;i++){ 31 if(G[cur][i] != father) {//dfs遍历 32 dfs(G[cur][i],cur); 33 } 34 } 35 } 36 int LCA(int u,int v){ 37 if(depth[u]<depth[v]) swap(u,v); 38 int dist = depth[u] - depth[v];//深度差 39 while(depth[u]!=depth[v]){//把较深的结点u倍增到与v高度相等 40 u = fa[u][Log[depth[u]-depth[v]]]; 41 } 42 if(u == v) return u;//如果u倍增到v,说明v是u的LCA 43 for(int i = Log[depth[u]];i>=0;i--){//否则两者同时向上倍增 44 if(fa[u][i]!=fa[v][i]){//如果向上倍增的祖先不同,说明是可以继续倍增 45 u = fa[u][i];//替换两个结点 46 v = fa[v][i]; 47 } 48 } 49 return fa[u][0];//最终结果为u v向上一层就是LCA 50 } 51 int main() 52 { 53 int t; 54 pre(); 55 scanf("%d",&t); 56 while(t--){ 57 scanf("%d",&N); 58 int root ; 59 int in[maxn]; 60 for(int i = 0;i<maxn;i++){ 61 G[i].clear() ; 62 } 63 memset(in,0,sizeof(in)); 64 int u,v; 65 for(int i = 0;i<N-1;i++){ 66 scanf("%d%d",&u,&v); 67 in[v] = 1; 68 G[u].push_back(v); 69 G[v].push_back(u); 70 } 71 for(int i = 1;i<=N;i++){//寻树的根结点 72 if(in[i] == 0) { 73 root = i; 74 break; 75 } 76 } 77 dfs(root,0); 78 scanf("%d%d",&u,&v); 79 int ans = LCA(u,v); 80 printf("%d\n",ans); 81 } 82 return 0; 83 } 84