LCA---Tarjan算法

       本问题中Tarjan算法不需要设置栈和dfn,low标号,而是设置了并查集。

         通过一次dfs遍历即可找出所有节点对的lca。将这样一次读取所有查询,计算一次后返回所有查询lca的算法称为离线算法 

         涉及到在线算法和离线算法这两个概念的算法还有区域最值查询问题(RMQ问题)。

      以下方法均可用于有向图【先查找出根节点root,再DFS】和无向图【root可以任意设置或者是直接遍历所有节点】

      原图和询问可以存储为【链式向前型】和【邻接表】的形式,注意定义形式即可。

【1】使用union函数

void LCA_Tarjan(int u)
{
	int now_to;
	int i;

	vis[u]=1;   //标记+访问+遍历
	ancestor[u]=u;
	for(i=Tnode[u].pre;i!=-1;i=Tedge[i].pre)
	{
		now_to=Tedge[i].to_vertex;
		if(!vis[now_to])
		{
			LCA_Tarjan(now_to);
			Union(u,now_to);
		        ancestor[Find(now_to)]=u;  //ancestor[Find(u)]=u;  效果一样
		}
	}
	for(i=Qnode[u].pre;i!=-1;i=Qedge[i].pre)
	{
		now_to=Qedge[i].to_vertex;
		if(vis[now_to])
		{
			lca[Qedge[i].num]=ancestor[Find(now_to)]; //单独开数组存储
                 //     Qedge[2*Qedge[i].num-1].ans=Qedge[2*Qedge[i].num].ans=ancestor[Find(now_to)];
		}
	}
}

【2】不使用union函数

void LCA_Tarjan(int u)
{ 
	int now_to;   
	int i; 
	
	vis[u]=1;  //标记+访问+遍历
	f[u]=u;   //将其父亲(根)指向自己
	for(i=Tnode[u].pre;i!=-1;i=Tedge[i].pre) /
	{
		now_to=Tedge[i].to_vertex;
		if(!vis[now_to])
		{
			LCA_Tarjan(now_to);
			f[now_to]=u;  //存储当前最近公共祖先
		}
	}

	for(i=Qnode[u].pre;i!=-1;i=Qedge[i].pre)  
	{
		now_to=Qedge[i].to_vertex;
		if(vis[now_to])  //如果其子节点及子节点的子树全部访问完才会进入这一步,由vis判断
		{                //如果已经访问了问题节点,就可以返回结果
	                lca[Qedge[i].num]=Find(now_to);
                   //	Qedge[2*Qedge[i].num-1].ans=Qedge[2*Qedge[i].num].ans=Find(now_to);  /*均可*/
		}
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值