输入一颗有根树,最后有一个询问,请输出询问中两个节点的最近公共祖先也就是LCA。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;
const int n = 10001;
bool root[n]; // 判断是否为根节点
bool vis[n];
int pre[n];
vector <int> e[n];//储存子节点
vector <int> q[n];//储存查询
int lca[n]; //储存最近公共祖先
int t, n1;
void init()
{
scanf("%d", &n1);
for(int i = 0; i <= n1; i++)
{
e[i].clear();
q[i].clear();
root[i] = true;
vis[i] = false;
pre[i] = i;
}
int a, b;
for(int i = 1; i < n1; i++)
{
scanf("%d %d", &a, &b);
e[a].push_back(b);
root[b] = false;
}
scanf("%d %d", &a, &b);
q[a].push_back(b);
q[b].push_back(a);
return;
}
int finn(int x)
{
int z, y = x;
while(y != pre[y])
{
y = pre[y];
}
while(x != pre[x])
{
z = pre[x];
pre[x] = y;
x = z;
}
return y;
}
void dataprocess(int x)
{
lca[x] = x;
int len = e[x].size();
for(int i = 0; i < len; i++)
{
dataprocess(e[x][i]); //求e[x][i]及其子节点等的lca
pre[e[x][i]] = x; // 合并,但是我们不需要专门的合并函数
}
vis[x] = true;
len = q[x].size();
for(int i = 0; i < len; i++)
{
if(vis[q[x][i]])
{
printf("%d\n", lca[finn(q[x][i])]);
}
return;
}
return;
}
int main()
{
scanf("%d", &t);
while(t--)
{
init();
for(int i = 1; i <= n; i++)
{
if(root[i])
{
dataprocess(i);
break;
}
}
}
}