题意:给n个结点,判断对于询问的两个结点的LCA;
这个和HDU 2586的区别是HDU 2586是求路径长度,无论你哪个结点为根结点,它的路径长度都是一定的,因为这个长度本身就是相对来求解;
而这一题它的根结点不能随便选取,必须要从没有父节点的点中选取,因此增加一个root[i]在输入时判断i结点是否有父节点;
然后选取一个满足题意的结点作为根结点,套个Tarjan模版就可以了;
注意还是判断同一子树结点时,如果res已经计算就不要再次计算;
Codes:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N=10002;
vector<int> edge[2*N];
vector<int> query[2*N];
int pre[N],vis[N],root[N];
int qu=0,qv=0;
int res=0;
int find(int i){
return i==pre[i]?i:pre[i]=find(pre[i]);
}
void tarjan(int u){
// system("pause");
for(int i=0;i<edge[u].size();i++){
int v=edge[u][i];
if(vis[v]) continue;
vis[v]=1;
tarjan(v);
pre[v]=u;
for(int j=0;j<query[v].size();j++){
int qv=query[v][j];
if(vis[qv]&&res==0){
res=find(qv);
}
}
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
res=0;
memset(vis,0,sizeof(vis));
for(int i=0;i<=n;i++){
pre[i]=i;
root[i]=1;
query[i].clear();
edge[i].clear();
}
for(int i=1;i<=n-1;i++){
int u,v;
scanf("%d %d",&u,&v);
edge[u].push_back(v);
edge[v].push_back(u);
root[v]=0;
}
scanf("%d %d",&qu,&qv);
query[qu].push_back(qv);
query[qv].push_back(qu);
for(int i=1;i<=n;i++){
if(root[i]){
vis[i]=1;
tarjan(i);
printf("%d\n",res);
break;
}
}
}
}