tarjan算法

以下内容为个人理解,有错误地方还请指出。


须知概念:

Dfs搜索树,回边,交叉边(无向图的dfs树不存在交叉边);

dfn[u] :u的dfs序

low[u] :从u或u的子孙出发,通过回边可以到达的最小的dfs序

 

对于Tarjan算法中,我们得到了dfn和low两个数组,

low[u]:=min(low[u],dfn[v])——(u,v)为回边,v不是u的子树;

low[u]:=min(low[u],low[v])——(u,v)为树枝边,v为u的子树;

 

下边对其进行讨论:

若low[v]>=dfn[u],则u为割点,u和它的子孙形成一个块。因为这说明u的子孙不能够通过其他边到达u的祖先,这样去掉u之后,图必然分裂为两个子图。

若low[v]>dfn[u],则(u,v)为割边。理由类似于上一种情况。

该算法要求图中不能有重边;

Tarjan 算法的任务就是算出每个点的low值,然后根据图的性质去使用low值。

可以用tarjan算法求解缩点,割点,割边,点双连通分量,边双联通分量,强连通分量等。

例题可参考

http://blog.csdn.net/u013569304/article/details/51146779

http://blog.csdn.net/u013569304/article/details/51146686


代码实现
//vector<int>head[maxn]; //耗时高
typedef vector<int>ve;
vector<ve>head(maxn);
int dep_tmp;
int dfn[maxn],low[maxn],dep[maxn],pre[maxn];//分别为dfs序,low值,节点深度,前继数组;
bool vis[maxn],cut_edge[maxn],cut_dot[maxn];//分别为标记数组,割边标记(记录深度较深的一段,(u,pre[u])就是割边),割点标记
int num;//割边数量
void tarjan_dfs(int rt,int father)
{
	int son=0;//rt的孩子数
	dfn[rt]=low[rt]=dep_tmp++;
	dep[rt]=dep[father]+1;
	vis[rt]=true;
	for(int i=0,len=head[rt].size();i<len;++i)
	{
		int v=head[rt][i];
		if(!vis[v])
		{
			son++;
			pre[v]=rt;
			tarjan_dfs(v,rt);
			low[rt]=min(low[rt],low[v]);
			if(low[v]>dfn[rt])
			{
					cut_edge[v]=true;
					num++;
			}
		}
		else if(v!=father)
			low[rt]=min(low[rt],dfn[v]);
//		if(low[v]>dfn[rt])//在这记录割边,如果有重边结果会错(偏大)
//		{
//				cut_edge[v]=true;
//				num++;
//		}
//		if( (rt!=root && low[v]>=dfn[rt])  ||  (rt==root && son>1))//割点
//		{
//			cut_dot[rt]=true;//标记割点
//		}
	}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LCA(最近公共祖先)是指在一棵树中,找到两个节点的最近的共同祖先节点。而Tarjan算法是一种用于求解强连通分量的算法,通常应用于有向图中。它基于深度优先搜索(DFS)的思想,通过遍历图中的节点来构建强连通分量。Tarjan算法也可以用于求解LCA问题,在有向无环图(DAG)中。 具体来说,在使用Tarjan算法求解LCA时,我们需要进行两次DFS遍历。首先,我们从根节点开始,遍历每个节点,并记录每个节点的深度(即从根节点到该节点的路径长度)。然后,我们再进行一次DFS遍历,但这次我们在遍历的过程中,同时进行LCA的查找。对于每个查询,我们将两个待查询节点放入一个查询列表中,并在遍历过程中记录每个节点的祖先节点。 在遍历的过程中,我们会遇到以下几种情况: 1. 如果当前节点已被访问过,说明已经找到了该节点的祖先节点,我们可以更新该节点及其所有后代节点的祖先节点。 2. 如果当前节点未被访问过,我们将其标记为已访问,并将其加入到查询列表中。 3. 如果当前节点有子节点,我们继续递归遍历子节点。 最终,对于每个查询,我们可以通过查询列表中的两个节点的最近公共祖先节点来求解LCA。 需要注意的是,Tarjan算法的时间复杂度为O(V+E),其中V为节点数,E为边数。因此,对于大规模的树结构,Tarjan算法是一种高效的求解LCA问题的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值