标签:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 24587 | Accepted: 12779 |
Description
Input
Output
Sample Input
2
16
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
5
2 3
3 4
3 1
1 5
3 5
Sample Output
4
3
Source
LCA(最近公共祖先)
先找到树根,之后倍增处理出每个点的祖先结点,然后同时上溯即可。
1 //lca 2 #include<algorithm> 3 #include<iostream> 4 #include<cstdio> 5 #include<cstring> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=10010; 10 int n; 11 vector<int> e[mxn]; 12 int fa[mxn][18]; 13 int dep[mxn]; 14 int in[mxn]; 15 void add_edge(int u,int v){ 16 e[u].push_back(v); 17 in[v]++; 18 } 19 void dfs(int u){//求点深度,倍增算祖先结点fa 20 for(int i=0;i<e[u].size();i++){ 21 int v=e[u][i]; 22 fa[v][0]=u; 23 dep[v]=dep[u]+1; 24 for(int j=1;(1<<j)<=dep[v];j++){ 25 fa[v][j]=fa[fa[v][j-1]][j-1]; 26 } 27 dfs(v); 28 } 29 return; 30 } 31 int lca(int a,int b){ 32 if(dep[a]<dep[b])swap(a,b);//(处理深度更大的那个) 33 for(int i=16;i!=-1;i--)//从高位开始试。(其实从低开始也一样?) 34 if(dep[a]>=dep[b]+(1<<i))a=fa[a][i];//此步结束后,a和b查找到的深度相同 35 if(a==b)return a; 36 for(int i=16;i!=-1;i--)//共同上溯 37 if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i]; 38 return fa[a][0]; 39 } 40 int main(){ 41 int T; 42 scanf("%d",&T); 43 int i,j; 44 while(T--){ 45 memset(dep,0,sizeof(dep)); 46 memset(fa,0,sizeof(fa)); 47 memset(in,0,sizeof(in)); 48 scanf("%d",&n); 49 for(i=1;i<=n;i++) e[i].clear(); 50 int u,v; 51 for(i=1;i<n;i++){ 52 scanf("%d%d",&u,&v); 53 add_edge(u,v); 54 } 55 int root=0; 56 for(i=1;i<=n;i++)if(in[i]==0){root=i;break;}//入度为0的那个点是根 57 dep[root]=1; 58 fa[root][0]=-1; 59 dfs(root); 60 int a,b; 61 scanf("%d%d",&a,&b); 62 printf("%d\n",lca(a,b)); 63 } 64 return 0; 65 }
POJ1330 Nearest Common Ancestors
标签:
原文地址:http://www.cnblogs.com/SilverNebula/p/5638944.html