图论: 割点、桥(割边)、强连通分量 学习笔记

//无向图的割点和桥: 

//cutnode[u]=true表示u是一个割点 
//cutedge(u,v)=true表示(u,v)是一条割边 
//Color[u]: 黑 访问完毕 灰 正在访问 白 未访问; 

Tarjan(u,father){
	DFN[u]=LOW[u]=++time;
	//LOW[u]: u以及u的子孙所能到达的最小时间戳
	Color[u]=灰;
	put u into a stack; //入栈 
	for each e=(u,v)
		if (color[v]==白){
			Tarjan(v,u);
			LOW[u]=min(LOW[u],LOW[v]);
			//若存在边(u,v),且DFN[u]<LOW[v],则(u,v)为一条割边
			if (DFN[u]<LOW[v]) cutedge(u,v)=true;
			
			//若存在边(u,v),且DFN[u]<=LOW[v],则u为一个割点;
			//当u为根,且至少有2棵子树
			//用son[u]记录u的儿子个数,当color[v]=白说明多一个儿子;
			son[u]++;
			if ((u==root && son[u]>1) || (u!=root && DFN[u]<=LOW[v]))
				cutnode[u]=true;
				
		}	else
		if (v!=father)
			LOW[u]=min(LOW[u],DFN[v]);
	Color[u]=黑; 
	
		//图中一些概念: 
		//点连通度: 最小割点集合中的点数
		//边连通度: 最小割边集合中的边数 
		//双连通分支: 可理解为任意两点之间有两条路径的极大的子图 
		//如果一个无向连通图的点/边连通度大于1,则称该图是点/边双连通的;
	
	//当访问结束回退时,若LOW[u]=DFN[u],则有一个双连通分支;
	if (LOW[u]==DFN[u]) pop until u;
		//弹出元素属于同一个双连通分支;
	
	//双连通分支缩点后会变成一棵树 
}



//有向图的强连通分量(分支):

//强连通: 有向图中两个点之间至少有1条路径
//强连通分量: 极大强连通子图; 

//与无向图的双连通分支求法一致;

//强连通分支会形成DAG(有向无环图)
 
 
 
//考虑以下问题: 
 
	//假设有一个无向图
	//求解最小加几条边,使得不存在桥
		//缩点后形成了一棵树
		//这棵树中度数为1的结点个数为x
		//答案就是(x+1)/2 
		//考虑消除所有度为1的结点即可,连边可以增加它们的度数;
	 

	//假设有一个有向图
	//求解最小加几条边,使得整张图强连通
		//首先求强连通分量缩点
		//然后在新的缩点的图中
		//求出入度为0点的个数为a,出度为0的点的个数为b
		//答案就是max{a,b}
		//想法也是简单的,尽量产生环; 
 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值