最近公共祖先(LCA)(洛谷)

该代码实现了一个基于广度优先搜索(BFS)的算法来寻找树中两个节点的最近公共祖先。算法首先初始化一个队列用于BFS,并通过层级遍历记录每个节点到根节点的距离。同时,使用动态规划优化查找最近公共祖先的过程。最后,输入两个节点,程序返回它们的最近公共祖先。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

P3379
代码:


#include<bits/stdc++.h>
using namespace std;
const int SIZE=500005;
int head[SIZE],nxt[SIZE*2],ver[SIZE*2],tot=0;
int n,m,s,t,d[SIZE],f[SIZE][20];
queue<int> q;
void add(int x,int y){
	ver[++tot]=y,nxt[tot]=head[x],head[x]=tot;
}
void bfs(){
	q.push(s);
	d[s]=1;
	while(!q.empty()){
		int x=q.front();
		q.pop();
		for(int i=head[x];i;i=nxt[i]){
			int y=ver[i];
			if(d[y]) continue;
			d[y]=d[x]+1;
			q.push(y);
			f[y][0]=x;
			for(int j=1;j<=t;j++)
				f[y][j]=f[f[y][j-1]][j-1];
		}
	}
}
int lca(int x,int y){
	if(d[x]>d[y]) swap(x,y);
	for(int i=t;i>=0;i--)
		if(d[f[y][i]]>=d[x]) y=f[y][i];
	if(x==y) return x;
	for(int i=t;i>=0;i--)
		if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
	return f[x][0];
}
int main(){
	scanf("%d%d%d",&n,&m,&s);
	t=(int)(log(n)/log(2))+1;
	for(int i=1;i<=n-1;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y),add(y,x);
	}
	bfs();
	for(int i=1;i<=m;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		printf("%d\n",lca(x,y));
	}
	return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Eq1Eo5tB-1633441199726)(https://api.nmb.show/1985acg.php)]

### 图论题目合集与学习资源 作为一个知名的在线编程学习平台,提供了大量的图论相关题目和学习资源。以下是关于图论题目合集及学习资料的详细介绍: #### 1. 图论基础题目集合 平台上包含了许多经典的图论题目,涵盖了拓扑排序、DFS、BFS、Floyd、Dijkstra、LCA最近公共祖先)、最小生成树、最短路径等内容。以下是一些推荐的基础图论题目集合[^1]: - **P3386 【模板】二分图最大匹配**:此题为二分图最大匹配的经典模板题,适合初学者练习匈牙利算法或网络流算法。 - **P3372 【模板】Kruskal 算法求最小生成树**:通过此题可以熟悉 Kruskal 算法实现最小生成树的过程。 - **P3373 【模板】Prim 算法求最小生成树**:Prim 算法是另一种求解最小生成树的方法,此题为其实现提供了一个良好的实践机会。 #### 2. 并查集相关题目 并查集是一种用于处理集合合并与查询问题的数据结构,在图论中有着广泛的应用。以下是一些与并查集相关的题目[^2]: - **P5836 [USACO19DEC]Milk Visits S【并查集】**:此题需要使用并查集来判断奶牛之间的连通性,并根据条件进行合并操作。 - **P2820 局域网【并查集 + 最小生成树】**:结合了并查集和最小生成树的知识点,要求计算局域网中的最优连接方式。 #### 3. 高级图论题目 对于已经掌握基础图论知识的学习者,可以尝试以下高级题目集合[^3]: - **P3629 [APIO2010]巡逻【树的直径】**:此题涉及树的直径计算,是一个经典的树形图论问题。 - **P4568 [JLOI2011]飞行路线【多源最短路径】**:此题需要使用 Floyd-Warshall 算法或其他多源最短路径算法来解决复杂图中的路径问题。 #### 4. 学习资源推荐 除了题目练习外,还提供了丰富的学习资料,帮助用户深入理解图论知识[^4]: - **题解区**:每道题目下方都有详细的题解,涵盖多种解法和优化技巧。 - **优快云 博客**:许多博主在 优快云 上分享了关于图论的学习笔记和经典题目解析,例如《图》经典题题解(拓扑排序,DFS,BFS,Floyd, Dijkstra, LCA 最近公共祖先,最小生成树,最短路径)。 - **OI Wiki**:这是一个开源的竞赛编程学习网站,其中包含了图论相关的理论知识和算法实现。 ```python # 示例代码:Kruskal 算法求最小生成树 def find(x, f): if f[x] == x: return x f[x] = find(f[x], f) return f[x] def kruskal(n, edges): edges.sort(key=lambda x: x[2]) f = list(range(n + 1)) mst = [] for u, v, w in edges: root_u = find(u, f) root_v = find(v, f) if root_u != root_v: f[root_u] = root_v mst.append((u, v, w)) return mst ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值