[POJ 1330]Nearest Common Ancestors[LCA](O(dep[u] + dep[v]))

题目链接: [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;
}


你可能感兴趣的:(LCA)