poj 1330 Nearest Common Ancestors LCA/DFS

来源:互联网 发布:淘宝网上批发市场 编辑:程序博客网 时间:2024/06/06 02:36

题目链接:

http://poj.org/problem?id=1330

题意:

求出两点间的最近公共祖先。

题解:

第一种:
并查集维护:http://www.cnblogs.com/procedure2012/archive/2012/01/29/2331468.html
利用并查集在每次对子树进行遍历时进行合并,因为对以x为根的子树的遍历时只有当x的所有子树都遍历过后才会把它合并到他父亲的集合里,所以当需要查找的两个节点q1、q2中q1已被遍历且q2正是当前遍历的节点时说明此时只有距他们最近的祖先是在集合里的(可能为q1或q2),所以只要找到已被遍历的q1所在集合的祖先就是这两的节点的LCA。
这里写图片描述

第二种
直接dfs:每次从u和v的depth较深的开始往上面找,然后如果一样就跳出,不一样继续找

代码:

并查集

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>using namespace std;typedef long long ll;#define MS(a) memset(a,0,sizeof(a))#define MP make_pair#define PB push_backconst int INF = 0x3f3f3f3f;const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;inline ll read(){    ll x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}//////////////////////////////////////////////////////////////////////////const int maxn = 1e4+10;vector<int> g[maxn];int f[maxn],vis[maxn],fa[maxn];int q1,q2;int a[maxn];int find(int x){    return fa[x]==x ? x : fa[x]=find(fa[x]);}void Union(int x,int y){    int p1=find(x),p2=find(y);    if(p1 == p2) return ;    fa[p1] = p2;}void dfs(int u){    for(int i=0; i<(int)g[u].size(); i++){        int v = g[u][i];        dfs(v);        Union(u,v); // 合并的时候是u合并到v上,u的父亲是v,利于下面寻找祖先,也就是所有u的父亲的祖先都是u        a[find(u)] = u; // u的所有孩子的祖先都是u    }    vis[u] = 1;    if(q1==u && vis[q2]) printf("%d\n",a[find(q2)]);    if(q2==u && vis[q1]) printf("%d\n",a[find(q1)]);    return ;}int main(){    int T = read();    while(T--){        int n = read();        for(int i=0; i<=n; i++) {            g[i].clear();            f[i] = 0;            fa[i] = i;            vis[i] = 0;            a[i] = 0;        }        int u,v;        for(int i=1; i<n; i++){            scanf("%d%d",&u,&v);            f[v] = 1;            g[u].push_back(v);        }        cin >> q1 >> q2;        int i;        for(i=1; i<=n; i++)            if(f[i]==0) break;        dfs(i);    }    return 0;}

直接找:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>using namespace std;typedef long long ll;#define MS(a) memset(a,0,sizeof(a))#define MP make_pair#define PB push_backconst int INF = 0x3f3f3f3f;const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;inline ll read(){    ll x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}//////////////////////////////////////////////////////////////////////////const int maxn = 1e4+10;vector<int> g[maxn];int d[maxn],p[maxn],f[maxn];void dfs(int u,int fa,int de){    p[u] = fa;    d[u] = de;    for(int i=0; i<(int)g[u].size(); i++){        int v = g[u][i];        if(v == fa) continue;        dfs(v,u,de+1);    }}int lca(int u,int v){    while(d[u] > d[v]) u = p[u];    while(d[v] > d[u]) v = p[v];    while(u != v){        u = p[u];        v = p[v];    }    return u;}int main(){    int T = read();    while(T--){        int n = read();        for(int i=0; i<=n; i++) {            g[i].clear();            f[i] = 0; d[i] = 0; p[i] = 0;        }        int u,v;        for(int i=1; i<n; i++){            scanf("%d%d",&u,&v);            f[v] = 1;            g[u].push_back(v);        }        int i;        for(i=1; i<=n; i++)            if(f[i]==0) break;        dfs(i,-1,0);        cin >> u >> v;        cout << lca(u,v) << endl;    }    return 0;}
0 0
原创粉丝点击