题目链接:http://poj.org/problem?id=1330
题意:T组样例,n-1条边,1次询问,求最近公共祖先。
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=10010;
int T,n;
int degree[maxn],vis[maxn];
int ancestor[maxn];
vector<int>tree[maxn];
vector<int>query[maxn];
int f[maxn],r[maxn];
void Make_Set(){
for(int i=0;i<=n;i++){
f[i]=i;
r[i]=1;
}
}
int find(int x){
return x==f[x]?x:f[x]=find(f[x]);
}
void Union(int a,int b){
int ra=find(a);
int rb=find(b);
if(ra==rb) return ;
if(r[ra]>r[rb]){
f[rb]=ra;
r[ra]+=r[rb];
}
else{
f[ra]=rb;
r[rb]+=r[ra];
}
}
void Tarjan(int root){
for(int i=0;i<tree[root].size();i++){
if(!vis[tree[root][i]]){
Tarjan(tree[root][i]);
Union(root,tree[root][i]);
ancestor[find(root)]=root;
}
}
vis[root]=1;
for(int i=0;i<query[root].size();i++){
if(vis[query[root][i]]){
printf("%d\n",ancestor[find(query[root][i])]);
}
}
}
void Init(){
Make_Set();
memset(vis,0,sizeof(vis));
memset(degree,0,sizeof(degree));
for(int i=0;i<=n;i++){
tree[i].clear();
query[i].clear();
ancestor[i]=i;
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
#endif
scanf("%d",&T);
while(T--){
scanf("%d",&n);
Init();
int x,y;
for(int i=0;i<n-1;i++){
scanf("%d%d",&x,&y);
tree[x].push_back(y);
degree[y]++;
}
scanf("%d%d",&x,&y);
query[x].push_back(y);
query[y].push_back(x);
int root;
for(int i=1;i<=n;i++){
if(!degree[i]){
root=i;
break;
}
}
Tarjan(root);
}
return 0;
}