Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 25625 | Accepted: 13271 |
Description
In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree. Node x is an ancestor of node y if node x is in the path between the root and node y. For example, node 4 is an ancestor of node 16. Node 10 is also an ancestor of node 16. As a matter of fact, nodes 8, 4, 10, and 16 are the ancestors of node 16. Remember that a node is an ancestor of itself. Nodes 8, 4, 6, and 7 are the ancestors of node 7. A node x is called a common ancestor of two different nodes y and z if node x is an ancestor of node y and an ancestor of node z. Thus, nodes 8 and 4 are the common ancestors of nodes 16 and 7. A node x is called the nearest common ancestor of nodes y and z if x is a common ancestor of y and z and nearest to y and z among their common ancestors. Hence, the nearest common ancestor of nodes 16 and 7 is node 4. Node 4 is nearer to nodes 16 and 7 than node 8 is.
For other examples, the nearest common ancestor of nodes 2 and 3 is node 10, the nearest common ancestor of nodes 6 and 13 is node 8, and the nearest common ancestor of nodes 4 and 12 is node 4. In the last example, if y is an ancestor of z, then the nearest common ancestor of y and z is y.
Write a program that finds the nearest common ancestor of two distinct nodes in a tree.
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
最近公共祖先模板題;
題意:求最近公共祖先。。。
首先是深搜,複雜度特別
特別
特別
特別
特別
高。
- #include<stdio.h>
- #include<string.h>
- #include<algorithm>
- using namespace std;
- const int maxm=10005;
- int father[maxm];
- bool vis[maxm];
- int main()
- {
- int n,i,j,k,sum,a,b,t,x,y;
- scanf("%d",&t);
- while(t--)
- {
- memset(vis,false,sizeof(vis));
- memset(father,-1,sizeof(father));
- scanf("%d",&n);
- for(i=1;i<n;i++)
- {
- scanf("%d%d",&x,&y);
- father[y]=x;
- }
- scanf("%d%d",&a,&b);
- while(b!=-1)
- {
- vis[b]=true;
- b=father[b];
- }
- while(!vis[a])
- a=father[a];
- printf("%d\n",a);
- }
- return 0;
- }
- /*
- 324
- 5
- 2 3
- 3 4
- 3 1
- 1 5
- 3 5
- */
tarjian離線法:
- #include<stdio.h>
- #include<algorithm>
- #include<string.h>
- #include<vector>
- using namespace std;
- const int maxm=10005;
- vector<int>v[maxm];
- vector<int>p[maxm];
- int father[maxm],vis[maxm],num[maxm],ans,n,flag[maxm];
- void tarjian(int x);
- int find(int k);
- void init();
- int main()
- {
- int i,j,k,t,sum,x,y;
- scanf("%d",&t);
- while(t--)
- {
- scanf("%d",&n);
- init();
- for(i=1;i<n;i++)
- {
- scanf("%d%d",&x,&y);
- flag[y]++;
- v[x].push_back(y);
- }
- scanf("%d%d",&x,&y);
- p[x].push_back(y);
- p[y].push_back(x);
- for(i=1;i<=n;i++)
- {
- if(!flag[i])
- tarjian(i);
- }
- printf("%d\n",ans);
- }
- return 0;
- }
- void init()
- {
- memset(vis,0,sizeof(vis));
- memset(flag,0,sizeof(flag));
- for(int i=1;i<=n;i++)
- {
- father[i]=i;
- v[i].clear();
- p[i].clear();
- }
- }
- void tarjian(int x)
- {
- int i,j;
- for(j=0;j<v[x].size();j++)
- {
- int xx=v[x][j];
- tarjian(xx);
- father[xx]=x;
- }
- vis[x]=1;
- for(j=0;j<p[x].size();j++)
- {
- int xx=p[x][j];
- if(vis[xx])
- {
- ans=find(xx);
- return;
- }
- }
- }
- int find(int k)
- {
- int x=k,i,j;
- while(father[x]!=x)
- x=father[x];
- i=k;
- while(father[i]!=x)
- {
- j=father[i];
- father[i]=x;
- i=j;
- }
- return x;
- }