#190-[LCA]Nearest Common Ancestors

版权声明:反正也没有人会转,下一个 https://blog.csdn.net/drtlstf/article/details/85011362

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;
}

猜你喜欢

转载自blog.csdn.net/drtlstf/article/details/85011362