Algorithm第四版算法 C++实现(十七)——kosaraju算法(计算强连通分支量)

强连通图(图指有向图):图中任意两点双向可达
强连通分支:图里与自己内部强连通但与整个图的其他部分不强连通的子图
kosaraju算法通过两次DFS来实现,第一次对有向图D进行搜索,并标记顺序;第二次对有向图D的反图(见有向图的构造revers方法)进行搜索。从构造函数进入dfs函数之后,只要不退出则说明之后遍历的都是连通的。

class kosaraju
{
private:
	bool *marked;
	int *id;
	int count;
	void dfs(digraph g, int v)
	{
		marked[v] = true;
		id[v] = count;
		for (int w : g.iterator(v))
		{
			if (!marked[w])
			{
				dfs(g, w);
			}
		}
	}
public:
	kosaraju(digraph g)
	{
		marked = new bool[g.numv()];
		id = new int[g.numv()];
		std::fill(marked, marked + g.numv(), 0);
		DFO order(g.reverse());
		for (auto s : order.rp_order())
		{
			if (!marked[s])
			{
				dfs(g, s);
				count++;
			}
		}
	}
	bool strongly_con(int v, int w)
	{
		return id[v] == id[w];
	}
	int in_id(int v)	//返回顶点所属的连通分支
	{
		return id[v];
	}
	int con_num()		//连通分支数
	{
		return count;
	}
};

这段代码的巧妙之处就在于我们使用上一期构造的BFO对象来对图的反图进行第一次遍历,这样如果我们就可以得到遍历之后进行拓扑排序的一个序列。然后我们根据这个序列的顺序来进行遍历,如果我们从构造函数进入DFS之后,不退出,那么后续的点都是强连通的。
证明如下:
dfs(g,s)从构造函数进入,然后进入dfs(v),证明存在s到v的路径s-v,有因为v之前并没有出现,所以在根据g反的拓扑排序中,v在s之后,及在g反中,存在从s到v的路径s-v,即在g中含有从v到路径v-s,即s与v是强连通的。证毕。

运行结果:

在这里插入图片描述
明显该图有5个连通分支

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值