标签:struct mes common memset ++ com 算法 dde ons
<题目链接>
题目大意:
给出一棵树,问任意两个点的最近公共祖先的编号。
解题分析:
LCA模板题,下面用的是在线倍增算法求解。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 const int N = 1e4+10; 8 const int INF = 0x3f3f3f3f; 9 struct Edge{ 10 int to,next; 11 }edge[N<<1]; 12 int cnt,head[N]; 13 int dep[N],f[N][35]; 14 int n,in[N]; 15 void addedge(int u,int v){ 16 edge[++cnt].to=v,edge[cnt].next=head[u]; 17 head[u]=cnt; 18 } 19 void dfs(int u,int fa){ //将所有节点的深度都标记出来 20 for(int i=head[u];~i;i=edge[i].next){ 21 int v=edge[i].to; 22 if(v==fa)continue; 23 if(!dep[v]){ 24 dep[v]=dep[u]+1; 25 f[v][0]=u; 26 dfs(v,u); 27 } 28 } 29 } 30 void init(){ //预处理倍增数组 31 for(int j=1;(1<<j)<=n;j++) 32 for(int i=1;i<=n;i++) 33 f[i][j]=f[f[i][j-1]][j-1]; 34 } 35 int LCA(int x,int y){ 36 if(dep[x]<dep[y])swap(x,y); 37 int d=dep[x]-dep[y]; 38 for(int i=0;(d>>i)!=0;i++) 39 if((d>>i)&1)x=f[x][i]; 40 if(x==y)return x; 41 for(int i=20;i>=0;i--) 42 if(f[x][i]!=f[y][i]){ 43 x=f[x][i]; 44 y=f[y][i]; 45 } 46 return f[x][0]; 47 } 48 int main(){ 49 int T;scanf("%d",&T); 50 while(T--){ 51 scanf("%d",&n); 52 cnt=0; 53 int u,v; 54 memset(head,-1,sizeof(head)); 55 for(int i=1;i<n;i++){ 56 scanf("%d%d",&u,&v); 57 addedge(u,v); 58 in[v]++; 59 } 60 memset(dep,0,sizeof(dep)); 61 int root; 62 for(int i=1;i<=n;i++) 63 if(!in[i])root=i; //找到该树的根 64 dep[root]=1; 65 dfs(root,-1); 66 init(); 67 scanf("%d%d",&u,&v); 68 printf("%d\n",LCA(u,v)); 69 } 70 return 0; 71 }
2018-10-18
POJ 1330 Nearest Common Ancestors (模板题) (LCA)【倍增】
标签:struct mes common memset ++ com 算法 dde ons
原文地址:https://www.cnblogs.com/00isok/p/9813871.html