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

来源:互联网 发布:大数据的真正意义是 编辑:程序博客网 时间:2024/05/16 15:42
题目链接:[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;}


0 0