您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: