tips:
1.finddad的过程就是回溯的过程
2.遍历完一个结点所有的子树后,该节点father才会更新
3.father是由下向上更新的,---这样处理出了LCA
4.ref:http://www.cnblogs.com/JVxie/p/4854719.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
//❤思路讲解:http://www.cnblogs.com/JVxie/p/4854719.html //具体实现:https://blog.csdn.net/hy1405430407/article/details/48181453 //有的题解还要记录深度 //参考题解: //主要:https://blog.csdn.net/zy704599894/article/details/52193936 //主要里面有路径压缩---当时卡了才理解,不过不用路径压缩也行 //https://www.cnblogs.com/sajuuk/p/4684536.html #include<cstdio> #include<vector> #include<cstring> //memset头文件 using namespace std; const int M=10010; int t; int n; bool vis[M]; int father[M]; vector<int > v[M]; vector<int > Q[M]; int root; int ans; void init(){ memset(vis,0,sizeof(vis)); for(int i=0;i<=n;i++){ father[i]=i; v[i].clear(); Q[i].clear(); } } int finddad(int x){ while(x != father[x]){ x=father[x]; } return father[x]; } void Tarjan(int x){ for(int i=0;i<v[x].size();i++){ Tarjan(v[x][i]); father[v[x][i]]=x; } vis[x]=1; //此时x == father[x]; //递归返回到x的上一层时才会改变 for(int i=0;i<Q[x].size();i++){ if(vis[Q[x][i]]){ ans=finddad(Q[x][i]); return ;//只有一组询问,所以直接return } } } int main(){ while(scanf("%d",&t)!=EOF){ while(t--){ scanf("%d",&n); init(); int x,y; for(int i=1;i<n;i++){//树 scanf("%d%d",&x,&y); v[x].push_back(y); vis[y]=1;//有入度 } //只有一组询问 scanf("%d%d",&x,&y); Q[x].push_back(y); Q[y].push_back(x); for(int i=1;i<=n;i++){ if(!vis[i]){//根结点 root=i; break; } } memset(vis,0,sizeof(vis)); Tarjan(root); printf("%d\n",ans); } } return 0; }