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)
The data set 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. The tree description is followed by a list of pairs of vertices, in the form:
nr_of_pairs
(u v) (x y) ...
The input contents several data sets (at least one).
Note that white-spaces (tabs, spaces and line breaks) can be used freely in the input.
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:
the program input and output is:
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)
Output
2:1
5:5
题意
给出一颗树, n 次查询最近公共祖先,输出所有查询所涉及到顶点的次数,未涉及则不输出。
思路
LCA模板,在输入查询的时候,用scanf(" (%d,%d)",&x,&y);输入,注意"("左边有一个空格
不知道为什么在POJ过不了,又是TLE又是MLE又是RE的,UVA,ZOJ,CSU都能过
代码
#include <iostream> #include <vector> #include <cstring> #include <cstdio> #include <algorithm> #define ll long long #define ull unsigned long long #define ms(a,b) memset(a,b,sizeof(a)) const int inf=0x3f3f3f3f; const ll INF=0x3f3f3f3f3f3f3f3f; const int maxn=1e6+10; const int mod=1e9+7; const int maxm=3e3+10; const int maxq=1e6+10; using namespace std; struct Edge { int to,Next; }edge[maxm<<1]; int head1[maxm]; int tot1; int ans[maxm]; void add_edge(int u,int v) { edge[tot1].to=v; edge[tot1].Next=head1[u]; head1[u]=tot1++; } struct Query { int to,Next; int index; }query[maxq]; int head2[maxm]; int tot2; void add_query(int u,int v,int index) { query[tot2].to=v; query[tot2].Next=head2[u]; query[tot2].index=index; head2[u]=tot2++; } int f[maxm]; int find(int x) { if(f[x]!=x) f[x]=find(f[x]); return f[x]; } void join(int x,int y) { int dx=f[x],dy=f[y]; if(dx!=dy) f[dy]=dx; } bool vis[maxm]; int fa[maxm]; int num[maxm]; void LCA(int u) { fa[u]=u; vis[u]=1; for(register int i=head1[u];~i;i=edge[i].Next) { int v=edge[i].to; if(vis[v]) continue; LCA(v); join(u,v); fa[find(u)]=u; } for(register int i=head2[u];~i;i=query[i].Next) { int v=query[i].to; if(vis[v]) ans[query[i].index]=fa[find(v)]; } } bool isroot[maxm]; inline void init(int n) { tot1=0;tot2=0; ms(head1,-1);ms(head2,-1); ms(vis,0);ms(isroot,true); ms(num,0); for(register int i=1;i<=n;i++) f[i]=i; } int main(int argc, char const *argv[]) { #ifndef ONLINE_JUDGE freopen("/home/wzy/in.txt", "r", stdin); freopen("/home/wzy/out.txt", "w", stdout); srand((unsigned int)time(NULL)); #endif int n; int cnt,h,p; while(scanf("%d",&n)==1) { init(n); for(register int i=1;i<=n;i++) { scanf("%d:(%d)",&h,&cnt); for(int j=0;j<cnt;j++) scanf("%d",&p),add_edge(p,h),add_edge(h,p),isroot[p]=false; } int root; for(register int i=1;i<=n;i++) if(isroot[i]) root=i; int q; scanf("%d",&q); int x,y; for(register int i=0;i<q;i++) { scanf(" (%d,%d)",&x,&y); add_query(x,y,i);add_query(y,x,i); } LCA(root); for(register int i=0;i<q;i++) num[ans[i]]++; for(register int i=1;i<=n;i++) if(num[i]) printf("%d:%d ",i,num[i]); } #ifndef ONLINE_JUDGE cerr<<"Time elapsed: "<<1.0*clock()/CLOCKS_PER_SEC<<" s."<<endl; #endif return 0; }