有向图的强连通分支及DAG

有向图的强连通分支:在有向图G中,如果任意两个不同的顶点相互可达,则称该图是强连通的。有向图G的极大连通子图为G的强连通分支;

图中每个节点只属于一个强连通分支;

有关DAG(有向无环图)的一些定理性质:(有时需要特殊考虑只有一个节点的时候)

1、DAG中唯一出度为0的点,一定可以由任意点出发可达。因为无环,所以从任何点出发,必然终止于一个出度为0的点;

2、DAG中,所有入度不为0的点一定可以由某个入度为0的点出发可达。因为无环,所以从入度不为0的点往回走,必然终止于一个入度为0的点;

3、在DAG中加max(n,m)(其中n为入度为0的点数,m为出度为0的点数)条边,能使DAG变成强连通的;即为每个入度为0的点添加入边,为每个出度为0的点添加出边;

有向图的强连通分支问题常通过求强连通分量,缩点,转化为DAG问题;


求解有向图强连通分量的Korasaju算法:(G的转置T和G具有相同的强连通分量)

1、深度优先遍历G,按照dfs完成的先后顺序将节点记录下来;

2、深度优先遍历G的转置图T,按照1中节点结束时间从大到小选择为遍历的起点,遍历T。遍历过程中给节点分类,每找到一个新的起点,分类就加1;

3、第二步产生的标记值相同的节点构成深度优先深林中的一棵树,即一个强连通分量;

算法时间复杂度为(V+E)

注意:Korasaju算法求强连通分量得到标记点,根据原图G对其缩点建DAG后,标记编号最大的点对应的一定是DAG中的出度为0的点,编号最小的点一定是DAG中的一个入度为0的点(特殊考虑原图本身就是双连通的,即缩点后只有一个点)

poj2186 Korasaju算法;

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<string>
#define ll long long
#define MAX 10010
#define INF INT_MAX
#define eps 1e-8

using namespace std;

struct Edge{
	int from,to;
};

vector<Edge>edges;
vector<int> G[MAX],T[MAX],A[MAX];
vector<int>S;

int n;

void init(){
	for (int i=0; i<= n; i++){
		G[i].clear();
		T[i].clear();
		A[i].clear();
	}
	S.clear();
	edges.clear();
}

int vis[MAX],sccno[MAX],scc_cnt;

void dfs1(int u){
	if (vis[u]) return;
	vis[u] 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值