Description
Description
树是一种计算机科学与工程知识的结构。举个例子:
在图中,每个节点都标有1~16的整数。节点8是树的根。如果节x位于根节点和节点y之间的路径中,则节点x是节点y的祖先。例如,节点4是节点16的祖先,节点10是节点16的祖先。事实上节点8,4,10和16都是节点16的祖先。请注意,节点是自己的祖先。节点8,4,6和7都是节点7的祖先。如果节点x是节点y的祖先和节点z的祖先,节点x被称为两个不同节点y和z的公共祖先。因此,节点8和节点4是节点16和7的共同祖先。 如果x是y和z的共同祖先,并且最接近y和z,则节点x被称为节点y和z的最近共同祖先。因此,节点16和7的最近的共同祖先是节点,因为节点4比节点8更接近于节点16和7。
再举些例子,节点2和3的最近的共同祖先是节点10,节点6和13的最近的共同祖先是节点8,并且节点4和12的最近的共同祖先是节点4。注意,如果y是z的祖先,则y和z的最近的共同祖先是y。
编写一个程序,找到树中两个不同节点的最近共同祖先。
Input
输入有多组测试用例。第一行是一个整数T(T<=100),代表测试数据的组数。每个测试用例第一行是一个整数N(N<=10000),代表树有N个节点。接下来的N-1行,每行有两个整数Ui,Vi,代表Ui是Vi的父亲。接下来是2个整数,你需要求出它们的最近公共祖先。
Output
每个测试用例输出一行,一个整数,代表询问的答案。
Sample Input
2
16
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
5
2 3
3 4
3 1
1 5
3 5
Sample Output
3
4
模板题
#include <iostream>
#include <cstring>
#include <vector>
#define SIZE 10010
using namespace std;
struct qedge
{
int to, id;
};
vector<qedge> qgraph[SIZE];
vector<int> graph[SIZE];
int pre[SIZE], indegree[SIZE], lca[SIZE];
bool visited[SIZE];
int find(int x) // 找祖先
{
return (pre[x] != x) ? pre[x] = find(pre[x]) : x;
}
void tarjan(int u) // 找LCA
{
int i, v;
for (i = 0; i < graph[u].size(); ++i)
{
v = graph[u][i];
tarjan(v);
pre[v] = u;
}
visited[u] = true;
for (i = 0; i < qgraph[u].size(); ++i)
{
v = qgraph[u][i].to;
if (visited[v])
{
lca[qgraph[u][i].id] = find(v);
}
}
return;
}
int main(void)
{
int t, n, u, v, i, root;
scanf("%d", &t);
while (t--) // 多组数据
{
scanf("%d", &n);
memset(visited, false, sizeof (visited)); // 初始化
memset(indegree, 0, sizeof (indegree));
for (i = 1; i <= n; ++i)
{
pre[i] = i;
graph[i].clear();
qgraph[i].clear();
}
for (i = 1; i < n; ++i)
{
scanf("%d%d", &u, &v);
graph[u].push_back(v);
++indegree[v]; // 有入度的不是根
}
scanf("%d%d", &u, &v);
qgraph[u].push_back({v, 1});
qgraph[v].push_back({u, 1});
for (root = 1; indegree[root] != 0; ++root); // 找根节点
tarjan(root);
printf("%d\n", lca[1]);
}
return 0;
}