poj 1330 Nearest Common Ancestors(LCA 基于二分搜索+st&rmq的LCA)
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 30147 | Accepted: 15413 |
Description
In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree. Node x is an ancestor of node y if node x is in the path between the root and node y. For example, node 4 is an ancestor of node 16. Node 10 is also an ancestor of node 16. As a matter of fact, nodes 8, 4, 10, and 16 are the ancestors of node 16. Remember that a node is an ancestor of itself. Nodes 8, 4, 6, and 7 are the ancestors of node 7. A node x is called a common ancestor of two different nodes y and z if node x is an ancestor of node y and an ancestor of node z. Thus, nodes 8 and 4 are the common ancestors of nodes 16 and 7. A node x is called the nearest common ancestor of nodes y and z if x is a common ancestor of y and z and nearest to y and z among their common ancestors. Hence, the nearest common ancestor of nodes 16 and 7 is node 4. Node 4 is nearer to nodes 16 and 7 than node 8 is.
For other examples, the nearest common ancestor of nodes 2 and 3 is node 10, the nearest common ancestor of nodes 6 and 13 is node 8, and the nearest common ancestor of nodes 4 and 12 is node 4. In the last example, if y is an ancestor of z, then the nearest common ancestor of y and z is y.
Write a program that finds the nearest common ancestor of two distinct nodes in a tree.
Input
Output
Sample Input
2
16
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
5
2 3
3 4
3 1
1 5
3 5
Sample Output
4
3
Source
#include<iostream>
#include<vector>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=;
const int logN=;
vector<int> G[N];
int root;
int parent[][N];
int fa[N],n,x,y,s,t;
int depth[N]; void dfs(int v,int p,int d)
{
parent[][v]=p;
depth[v]=d;
for(int i=;i<G[v].size();i++)
if (G[v][i]!=p)
{
fa[G[v][i]]=v;
dfs(G[v][i],v,d+);
}
}
void init(int V)
{
int root;
for(int i=;i<=n;i++)
if (fa[i]==) {root=i; break;}
dfs(root,-,);
for(int k=;k+<logN;k++)
{
for(int v=;v<=V;v++)
{
if(parent[k][v]<) parent[k+][v]=-;
else parent[k+][v]=parent[k][parent[k][v]];
}
}
}
int lca(int u,int v)
{
if (depth[u]>depth[v]) swap(u,v);
for(int k=;k<logN;k++)
{
if ((depth[v]-depth[u])>>k & )
v=parent[k][v];
}
if (u==v) return u;
for(int k=logN-;k>=;k--)
{
if (parent[k][u]!=parent[k][v])
{
u=parent[k][u];
v=parent[k][v];
}
}
return parent[][u];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=;i<=n;i++) {G[i].clear(); fa[i]=;}
for(int i=;i<=n-;i++)
{
scanf("%d%d",&x,&y);
G[x].push_back(y);
fa[y]=x;
}
init(n);
scanf("%d%d",&s,&t);
int croot=lca(s,t);
printf("%d\n",croot);
}
return ;
}
ST&RMQ 的LCA
#include<iostream>
#include<vector>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=;
const int M=;
int tot,cnt,n,T,s,t;
int head[N]; //记录i节点在e数组中的其实位置
int ver[*N]; //ver:保存遍历的节点序列,长度为2n-1,从下标1开始保存
int R[*N]; // R:和遍历序列对应的节点深度数组,长度为2n-1,从下标1开始保存
int first[N]; //first:每个节点在遍历序列中第一次出现的位置
bool vis[N]; //遍历时的标记数组
int dp[*N][M],fa[N]; struct edge
{
int u,v,next;
}e[*N];
void dfs(int u ,int dep)
{
vis[u] = true;
ver[++tot] = u;
first[u] = tot;
R[tot] = dep;
for(int k=head[u]; k!=-; k=e[k].next)
if( !vis[e[k].v] ) //这里可以省个vis数组,如果在dfs改成dfs(当前节点,当前节点的父亲,当前节点的深度) 具体可以参照connections with cities {
int v=e[k].v;
dfs(v,dep+);
ver[++tot]=u;
R[tot]=dep;
}
}
void ST(int n)
{
for(int i=;i<=n;i++)
dp[i][] = i;
for(int j=;(<<j)<=n;j++)
{
for(int i=;i+(<<j)-<=n;i++)
{
int a = dp[i][j-] , b = dp[i+(<<(j-))][j-];
dp[i][j] = R[a]<R[b]?a:b;
}
}
} int RMQ(int l,int r)
{
int k=(int)(log((double)(r-l+))/log(2.0));
int a = dp[l][k], b = dp[r-(<<k)+][k]; //保存的是编号
return R[a]<R[b]?a:b;
} int LCA(int u ,int v)
{
int x = first[u] , y = first[v];
if(x > y) swap(x,y);
int res = RMQ(x,y);
return ver[res];
} void addedge(int u,int v)
{
e[++cnt].u=u;
e[cnt].v=v;
e[cnt].next=head[u];
head[u]=cnt;
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
memset(fa,,sizeof(fa));
cnt=; tot=;
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y);
fa[y]=x;
}
for(int i=;i<=n;i++)
if (fa[i]==) { dfs(i,); break;}
ST(*n-);
scanf("%d%d",&s,&t);
printf("%d\n",LCA(s,t));
}
return ;
}
poj 1330 Nearest Common Ancestors(LCA 基于二分搜索+st&rmq的LCA)的更多相关文章
- POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)
POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...
- POJ - 1330 Nearest Common Ancestors(基础LCA)
POJ - 1330 Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000KB 64bit IO Format: %l ...
- POJ.1330 Nearest Common Ancestors (LCA 倍增)
POJ.1330 Nearest Common Ancestors (LCA 倍增) 题意分析 给出一棵树,树上有n个点(n-1)条边,n-1个父子的边的关系a-b.接下来给出xy,求出xy的lca节 ...
- POJ 1330 Nearest Common Ancestors(lca)
POJ 1330 Nearest Common Ancestors A rooted tree is a well-known data structure in computer science a ...
- POJ 1330 Nearest Common Ancestors 倍增算法的LCA
POJ 1330 Nearest Common Ancestors 题意:最近公共祖先的裸题 思路:LCA和ST我们已经很熟悉了,但是这里的f[i][j]却有相似却又不同的含义.f[i][j]表示i节 ...
- LCA POJ 1330 Nearest Common Ancestors
POJ 1330 Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 24209 ...
- POJ 1330 Nearest Common Ancestors 【LCA模板题】
任意门:http://poj.org/problem?id=1330 Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000 ...
- POJ 1330 Nearest Common Ancestors (LCA,dfs+ST在线算法)
Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 14902 Accept ...
- POJ 1330 Nearest Common Ancestors(Targin求LCA)
传送门 Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 26612 Ac ...
随机推荐
- Package libvirt was not found in the pkg-config search path
关于pip安装libvirt-python的时候提示Package libvirt was not found in the pkg-config search path的问题解决方法 1.一开始以为 ...
- Python3基础 file read 读取txt文件的前几个字符
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- Linux多线程--使用互斥量同步线程【转】
本文转载自:http://blog.csdn.net/ljianhui/article/details/10875883 前文再续,书接上一回,在上一篇文章:Linux多线程——使用信号量同步线程中, ...
- PMBOK十大知识领域是什么?
PMBOK十大知识领域是:整合管理.范围管理.时间管理.成本管理.质量管理.人力资源管理.沟通管理.风险管理.采购管理.干系人管理. 各用一句话概括项目管理知识体系十大知识领域: 1.整合管理:其作用 ...
- jQuery ajax 添加头部参数跨域
1.添加HTTP文件头 $.ajax({ url: "http://www.baidu.com", //contentType: "text/html; charset= ...
- Linq in GroupBy GroupJoin
还是上一份的代码例子: public class Person { public int ID { get; set; } public string Name { get; set; } publi ...
- Pytorch版本yolov3源码阅读
目录 Pytorch版本yolov3源码阅读 1. 阅读test.py 1.1 参数解读 1.2 data文件解析 1.3 cfg文件解析 1.4 根据cfg文件创建模块 1.5 YOLOLayer ...
- Apache+Php+Mariadb+NFS+discuz
安装LAMP服务器,并利用discuz做测试 nfs + discuz 192.168.108.158 php + DNS 192.168.108.160 apache ...
- UVa 10905 孩子们的游戏
https://vjudge.net/problem/UVA-10905 题意: 给定n个正整数,把它们连接成一个最大的整数. 思路: 实在是没想到直接用string来排序了. #include< ...
- 深蓝色 --ppt
Deep Learning of Binary Hash Codes for Fast Image Retrieval [Paper] [Code-Caffe] 1. 摘要 针对图像检索问题,提出简单 ...