题目链接:
[POJ 1330]Nearest Common Ancestors[LCA](O(dep[u] + dep[v]))
题意分析:
求两个结点的最近公共祖先。
解题思路:
先找出根结点,然后从根结点开始,运用深搜给每个子节点标记深度和父节点。
那么查找公共祖先时,只需将较矮的那个节点往上提到两个节点变为相同高度,
一起往上搜索即可。复杂度:dep[u] + dep[v]
个人感受:
这种做法还是很好理解撒,不过这种做法求单对是O(n)的复杂度,其它类型得换种算法。
先从基础开始~
具体代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int INF = 0x7f7f7f7f;
const int MAXN = 1e4 + 111;
vector<int> G[MAXN];
int rt, pa[MAXN], dep[MAXN];
void dfs(int v, int p, int d)
{
pa[v] = p;
dep[v] = d;
for (int i = 0; i < G[v].size(); ++i)
{
if (G[v][i] != p) dfs(G[v][i], v, d + 1);
}
}
void init()
{
dfs(rt, -1, 0);
}
int lca(int u, int v)
{
while (dep[u] > dep[v]) u = pa[u];
while (dep[v] > dep[u]) v = pa[v];
while (u != v)
{
u = pa[u];
v = pa[v];
}
return u;
}
int main()
{
int n, t; scanf("%d", &t);
while (t --)
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i) G[i].clear(), pa[i] = -1;
int up = n - 1, u, v;
for (int i = 0; i < up; ++i)
{
scanf("%d%d", &u, &v);
pa[v] = u;
G[u].push_back(v);
}
int who = 1;
while (pa[who] != -1) who = pa[who];
rt = who;
init();
int a, b;
scanf("%d%d", &a, &b);
printf("%d\n", lca(a, b));
}
return 0;
}