Closest Common Ancestors
Write a program that takes as input a rooted tree and a list of pairs of vertices. For each pair (u,v) the program determines the closest common ancestor of u and v in the tree. The closest common ancestor of two nodes u and v is the node w that is an ancestor of both u and v and has the greatest depth in the tree. A node can be its own ancestor (for example in Figure 1 the ancestors of node 2 are 2 and 5)
Input
The data set, which is read from a the std input, starts with the tree description, in the form:
nr_of_vertices
vertex:(nr_of_successors) successor1 successor2 ... successorn
...
where vertices are represented as integers from 1 to n ( n <= 900 ). The tree description is followed by a list of pairs of vertices, in the form:
nr_of_pairs
(u v) (x y) ...
The input file contents several data sets (at least one).
Note that white-spaces (tabs, spaces and line breaks) can be used freely in the input.
nr_of_vertices
vertex:(nr_of_successors) successor1 successor2 ... successorn
...
where vertices are represented as integers from 1 to n ( n <= 900 ). The tree description is followed by a list of pairs of vertices, in the form:
nr_of_pairs
(u v) (x y) ...
The input file contents several data sets (at least one).
Note that white-spaces (tabs, spaces and line breaks) can be used freely in the input.
Output
For each common ancestor the program prints the ancestor and the number of pair for which it is an ancestor. The results are printed on the standard output on separate lines, in to the ascending order of the vertices, in the format: ancestor:times
For example, for the following tree:
For example, for the following tree:
Sample Input
5 5:(3) 1 4 2 1:(0) 4:(0) 2:(1) 3 3:(0) 6 (1 5) (1 4) (4 2) (2 3) (1 3) (4 3)
Sample Output
2:1 5:5
Hint
Huge input, scanf is recommended.
题意:求最近公共祖先,模板题。
1 #include <iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<queue> 6 #include<map> 7 #include<algorithm> 8 typedef long long ll; 9 using namespace std; 10 const int MAXN=1e3+10; 11 int m,n; 12 int visit[MAXN]; 13 int is_root[MAXN]; 14 int str[MAXN]; 15 int head[MAXN];//以第i条边为起点的最后输入的那个编号 16 int ans[MAXN]; 17 int mp[MAXN][MAXN]; 18 int cnt,root,x,y,cx,cy; 19 struct node 20 { 21 int to;//边的终点 22 int next;//与第i条边同起点的一条边的存储位置 23 int vi;//权值 24 }edge[MAXN]; 25 void add_edge(int x,int y) 26 { 27 edge[cnt].to=y; 28 edge[cnt].next=head[x]; 29 head[x]=cnt++; 30 } 31 void init() 32 { 33 cnt=1; 34 memset(visit,0,sizeof(visit)); 35 memset(mp,0,sizeof(mp)); 36 memset(ans,0,sizeof(ans)); 37 memset(is_root,true,sizeof(is_root)); 38 memset(head,-1,sizeof(head)); 39 for(int i=1;i<=m;i++) 40 { 41 str[i]=i; 42 } 43 int p,k; 44 for(int i=1;i<=m;i++) 45 { 46 scanf("%d:(%d)",&p,&k); 47 for(int j=1;j<=k;j++) 48 { 49 scanf("%d",&x); 50 add_edge(p,x); 51 is_root[x]=false; 52 } 53 54 } 55 for(int i=1;i<=m;i++)//找根节点(入度为0的点) 56 { 57 if(is_root[i]) 58 { 59 root=i; 60 break; 61 } 62 } 63 } 64 int Find(int x) 65 { 66 int temp=x; 67 while(temp!=str[temp]) 68 { 69 temp=str[temp]; 70 } 71 return temp; 72 } 73 void Unit(int x,int y) 74 { 75 int root1=Find(x); 76 int root2=Find(y); 77 if(root1!=root2) 78 { 79 str[y]=root1; 80 } 81 } 82 void LCA(int u) 83 { 84 for(int i=head[u];i!=-1;i=edge[i].next) 85 { 86 int v=edge[i].to; 87 LCA(v); 88 Unit(u,v); 89 visit[v]=true; 90 } 91 for(int i=1;i<=m;i++)//遍历图中所有点,找出与当前顶点u有关系的点,若该点i已访问,则找到v,i的lca; 92 { 93 if(visit[i]&&mp[u][i]) 94 { 95 int k=Find(i); 96 ans[k]+=mp[u][i]; 97 } 98 } 99 } 100 void solve() 101 { 102 scanf("%d",&n); 103 for(int i=1;i<=n;i++) 104 { 105 scanf(" (%d%d)",&cx,&cy); 106 mp[cx][cy]++; 107 mp[cy][cx]++; 108 } 109 LCA(root); 110 } 111 void output() 112 { 113 for(int i=1;i<=m;i++) 114 { 115 if(ans[i]) 116 { 117 printf("%d:%d\n",i,ans[i]); 118 } 119 } 120 } 121 int main() 122 { 123 while(scanf("%d",&m)!=-1) 124 { 125 init(); 126 solve(); 127 output(); 128 } 129 return 0; 130 }
本文来自博客园,作者:左手边五十米,转载请注明原文链接:https://www.cnblogs.com/moomcake/p/9417601.html