题目:为了进入世界杯决赛圈,中国正在疯狂规划外援,但是足协要求外援必须要有中国血统。据了解在西班牙黄加马得李队效力的huxiaotaostasy和英国曼红队效力的yzm007有一个共同的中国血统的祖先Ginstein。现在足协已经草拟了一份规划球员名单和他们的祖先(这是一份庞大的名单追溯到所有球员的祖先女娲),足协想知道这份名单里任意两个人的公共祖先是谁
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
struct node{
int v,nxt;
}e[maxn];
int head[maxn],tot,fa[maxn],vis[maxn],in[maxn];
int n,ansx,ansy;
void init(){
tot=1;
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
memset(in,0,sizeof(in));
}
inline void add(int u,int v){
e[tot].v=v;
e[tot].nxt=head[u];
head[u]=tot++;
}
int find_x(int x){
if(x==fa[x])return x;
else return fa[x]=find_x(fa[x]);
}
void tarjan(int u){
fa[u]=u;
//vis[u]=1;
for(int i=head[u];i!=-1;i=e[i].nxt){
int v=e[i].v;
tarjan(v);
fa[v]=u;
}
vis[u]=1;//注意必须在回溯之后才标记vis[u],因为只有tarjan离线算法中的u代表相对较晚访问到的点。反过来想如果是回溯前的话,那答案一定是错的,可以自己手动模拟几遍
if(u==ansx&&vis[ansy])cout<<find_x(ansy)<<endl;
if(u==ansy&&vis[ansx])cout<<find_x(ansx)<<endl;
}
int main(){
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--){
init();
cin>>n;
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
add(x,y);
in[y]++;
}
int root;
for(int i=1;i<=n;i++){
if(in[i]==0){
root=i;
break;
}
}
cin>>ansx>>ansy;
tarjan(root);
}
}