LCA Tarjan及倍增模板(POJ 1330)

本文介绍了两种求最低公共祖先(LCA)的算法:Tarjan算法和倍增法。Tarjan算法是一种离线算法,通过深度优先搜索和并查集实现;倍增法则是一种在线算法,利用DFS预处理每个节点的深度及祖先信息。

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

我目前学会的两种求LCA的算法:

 

A、Tarjan算法(离线算法)

 

算法思路:

1、从根结点开始dfs。

2、遍历点x的所有子节点。

3、从某一个子节点y返回x时,要在并查集中把x,y所在的两棵子树合并,且根节点为点x所在子树的根节点。

4、离开结点x前,要看看是否有与x相关的询问(x,y),如果有且结点y已被访问过,(x,y)的LCA就是并查集中点y所在子树的根节点。

注意各个步骤实现的顺序:递归 - > 合并 - > 查找询问 - > 返回

 

代码:

 

#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;

int n;
vector<int> a[10005];
int ask1,ask2;
bool use1,use2;

int fa[10005]= {0};
int find(int x) {
	if(fa[x]==0) {
		return x;
	}
	return fa[x]=find(fa[x]);
}

bool flag=false;
void lca(int x) {
	if(x==ask1) use1=true;
	if(x==ask2) use2=true;
	for(int i=0; i<a[x].size(); i++) {
		lca(a[x][i]);
		fa[a[x][i]]=x;
	}
	if(x==ask1&&use2==true&&flag==false) {
		printf("%d\n",find(ask2));
		flag=true;
	} else if(x==ask2&&use1==true&&flag==false) {
		printf("%d\n",find(ask1));
		flag=true;
	}

	return ;
}

int main() {

	int t;
	scanf("%d",&t);
	while(t--) {
		
		bool root[10005]={0};
		scanf("%d",&n);
		use1=use2=false;
		flag=false;
		for(int i=1; i<=n; i++) {
			a[i].clear();
			root[i]=true;
			fa[i]=0;
		}
		for(int i=1; i<=n-1; i++) {
			int x,y;
			scanf("%d%d",&x,&y);
			a[x].push_back(y);
			root[y]=false;
		}
		scanf("%d%d",&ask1,&ask2);
		for(int i=1;i<=n;i++){
			if(root[i]==true){
				lca(i);
			}
		}
	}

	return 0;
}

------------------------------------------------------------------------------------------------------------------------------------------------------------

B、倍增法(在线算法)

 

算法思路:

1、进行一次dfs,初始化出每一个节点x的深度deep[x]以及上2^i层的祖先anc[x][i]。

2、调整询问的x(deep[x]>deep[y])结点高度,让x、y结点在同一高度。

3、同时倍增x、y两结点,求出LCA。

倍增时,i从大到小循环,每当anc[x][i]!=anc[y][i]时,就说明最近公共祖先在x,y的上2^i层与上2^(i+1)层之间,就将x,y变为anc[x][i],anc[y][i],再次重复刚刚的步骤(类似二分搜索)。

 

代码:

 

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;

int n;
vector<int> a[10005];

int anc[10005][20]= {0};
int deep[10005]= {0};
void dfs(int x,int fa) {
	anc[x][0]=fa;
	for(int i=1; i<=15; i++) {
		anc[x][i]=anc[anc[x][i-1]][i-1];
	}

	for(int i=0; i<a[x].size(); i++) {
		deep[a[x][i]]=deep[x]+1;
		dfs(a[x][i],x);
	}

	return ;
}

int LCA(int x,int y) {
	if(deep[x]<deep[y]) swap(x,y);
	for(int i=15; i>=0; i--) {
		if (deep[y]<=deep[anc[x][i]]) {
			x=anc[x][i];
		}
	}
	if(x==y) return x;

	for(int i=15; i>=0; i--) {
		if(anc[x][i]!=anc[y][i]) {
			x=anc[x][i],y=anc[y][i];
		}
	}
	return anc[x][0];
}

int main() {
	int t;
	scanf("%d",&t);
	while(t--) {
		bool root[10005]= {0};
		memset(root,true,sizeof(root));
		scanf("%d",&n);
		for(int i=1; i<=n; i++) {
			a[i].clear();
		}
		memset(anc,0,sizeof(anc));
		memset(deep,0,sizeof(deep));
		deep[0]=-1;
		
		for(int i=1; i<=n-1; i++) {
			int x,y;
			scanf("%d%d",&x,&y);
			a[x].push_back(y);
			root[y]=false;
		}
		for(int i=1; i<=n; i++) {
			if(root[i]==true) {
				dfs(i,0);
				break;
			}
		}
		int ask1,ask2;
		scanf("%d%d",&ask1,&ask2);
		printf("%d\n",LCA(ask1,ask2));
	}

	return 0;
}

 

 

 

 

 

 

 

内容概要:该论文聚焦于T2WI核磁共振图像超分辨率问题,提出了一种利用T1WI模态作为辅助信息的跨模态解决方案。其主要贡献包括:提出基于高频信息约束的网络框架,通过主干特征提取分支和高频结构先验建模分支结合Transformer模块和注意力机制有效重建高频细节;设计渐进式特征匹配融合框架,采用多阶段相似特征匹配算法提高匹配鲁棒性;引入模型量化技术降低推理资源需求。实验结果表明,该方法不仅提高了超分辨率性能,还保持了图像质量。 适合人群:从事医学图像处理、计算机视觉领域的研究人员和工程师,尤其是对核磁共振图像超分辨率感兴趣的学者和技术开发者。 使用场景及目标:①适用于需要提升T2WI核磁共振图像分辨率的应用场景;②目标是通过跨模态信息融合提高图像质量,解决传统单模态方法难以克服的高频细节丢失问题;③为临床诊断提供更高质量的影像资料,帮助医生更准确地识别病灶。 其他说明:论文不仅提供了详细的网络架构设计与实现代码,还深入探讨了跨模态噪声的本质、高频信息约束的实现方式以及渐进式特征匹配的具体过程。此外,作者还对模型进行了量化处理,使得该方法可以在资源受限环境下高效运行。阅读时应重点关注论文中提到的技术创新点及其背后的原理,理解如何通过跨模态信息融合提升图像重建效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值