poj 1330 Nearest Common Ancestors LCA/DFS
2017-04-11 23:58
281 查看
题目链接:
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> # 4000 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_back const 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_back const 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; }
相关文章推荐
- 【poj 1330】 Nearest Common Ancestors
- poj 1330 Nearest Common Ancestors(LCA模板)
- POJ 1330 最近公共祖先LCA_Tarjan 【水】
- poj 1330 Nearest Common Ancestors 题解
- poj 1330 Nearest Common Ancestors
- POJ 1330 Tarjan LCA、ST表(其实可以数组模拟)
- poj - 1330 - Nearest Common Ancestors
- poj 1330 最近公共祖先
- poj1330——Nearest Common Ancestors
- POJ1330 LCA/给树的节点标记层数
- poj 1330 Nearest Common Ancestors(并查集?!二分查找)
- poj1330( 树的先跟遍历)
- POJ1330(Nearest Common Ancestors)
- POJ 1330 Nearest Common Ancestors【LCA_(rmq 在线 + tarjan 离线)】
- poj 1330 LCA最近公共祖先
- LCA问题 poj1330 / poj1470
- poj 1330 Nearest Common Ancestors LCA targin
- poj1330,JDOJ3055部分分LCA(n^2暴力算法)
- poj 1330(最近公共祖先)
- poj 1330 Nearest Common Ancestors (LCA)