Closest Common Ancestors
Description有一颗树,求给定两节点的公共祖先,最后输出每个节点当做祖先的次数。 Input 输入文件包含多组测试数据。 Output对于每组数据输出若干行,每行形式为“a:b”,表示结点a做公共祖先有b次,按照结点a的字典顺序输出。 Sample Input5 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 Output2:1 5:5 Hint
|
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
inline int read() {
int data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=data*10+ch-'0',ch=getchar();
return data*w;
}
const int maxn=905;
struct point {
int to,next;
};
point a[maxn*2];
int cnt=0,h[maxn];
void add(int x,int y) {
a[++cnt].next=h[x];
a[cnt].to=y;
h[x]=cnt;
}
int f[maxn][21],hi[maxn];
void bfs(int x) {
for(int i=1; i<=20; i++)f[x][i]=f[f[x][i-1]][i-1];
for(int i=h[x]; i; i=a[i].next) {
int v=a[i].to;
hi[v]=hi[x]+1;
bfs(v);
}
}
int LCA(int x,int y) {
if(hi[x]<hi[y])swap(x,y);
for(int i=20; i>=0; i--)if(hi[f[x][i]]>=hi[y])x=f[x][i];
if(x==y)return x;
for(int i=20; i>=0; i--) {
if(f[x][i]!=f[y][i]) {
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
int ans[maxn];
int main() {
int n,m,x,y;
while(cin>>n) {
memset(ans,0,sizeof(ans));
memset(f,0,sizeof(f));
memset(hi,0,sizeof(hi));
memset(h,0,sizeof(h));
cnt=0;
for(int i=1; i<=n; i++) {
y=read();
m=read();
for(int j=1; j<=m; j++) {
x=read();
add(y,x);
f[x][0]=y;
}
}
x=1;
while(f[x][0]!=0)x=f[x][0];
hi[x]=1;
bfs(x);
cin>>m;
for(int i=1; i<=m; i++) {
x=read();
y=read();
ans[LCA(x,y)]++;
}
for(int i=1; i<=n; i++)if(ans[i])cout<<i<<":"<<ans[i]<<endl;
}
return 0;
}
Hint
So easy!