对刘汝佳蓝书点双连通分量(BCC)模板的理解

/*
	经过简单的使用,对刘汝佳的这个板做几个简单的说明:
	1、算法结束后每个bcc[i]里存入一个双连通分量的点的标号,其中割点也被存进去,也就是说割点可以属于多个双连通分量
	2、根据刘汝佳所说的点—双连通的要求,“任意两条边都在一个简单环中”,但是从代码中看到只要找到割点就要开始组一个连通分量了,
       那么问题就来了,如果割点的两侧都不是环呢?
	   比如对一棵树来说,任一点都是割点,点的两侧都是一条边,没有环,那怎么算他的双连通分量呢?
	   根据调试跟踪的结果,对一棵树来说一条边所关联的两点就是一个点双连通分量,也就是说,两个相邻的割点也各自被认作了一个双连通分量
	3、割点的bccno没有意义,因为割点属于多个双连通分量
	4、蓝书上认为没必要清空stack S,保险起见我给加上了
*/
#include
#include
#include
#include
#include
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
const int maxn = 10000 + 5;
struct Edge
{
	int u, v;
};
int iscut[maxn], pre[maxn], bccno[maxn], dfs_clock, bcc_cnt;
vectorG[maxn], bcc[maxn];
stackS;
int dfs(int u, int fa)
{
	int lowu = pre[u] = ++dfs_clock;
	int child = 0;
	for (int i = 0; i= pre[u]){
				iscut[u] = 1;
				bcc_cnt++;  bcc[bcc_cnt].clear();
				for (;;){
					Edge x = S.top();       S.pop();
					if (bccno[x.u] != bcc_cnt){
						bcc[bcc_cnt].push_back(x.u);
						bccno[x.u] = bcc_cnt;
					}
					if (bccno[x.v] != bcc_cnt){
						bcc[bcc_cnt].push_back(x.v);
						bccno[x.v] = bcc_cnt;
					}
		/*造成上述第二条的一个重要原因就是这个判断放在了上面两个if语句之下,所以这条跳出边的两端点已被加入了bcc[bcc_cnt]中;
	      另外,这条跳出的边是bcc内部的边,不是外部的边;
		*/
					if (x.u == u &&x.v == v){  
						break;
					}
				}
			}
		}
		else if (pre[v]= pre[root],所以在上面的判断中已经被视为一个割点,因此将他所在的连通分量作为一个点连通分量存储起来了,
	并且将其所关联得边从栈中清空,因此不会发生漏掉根节点所在连通分量的情况
*/	
	return lowu;
}
void find_bcc(int n)
{
	mem(pre, 0);
	mem(bccno, 0);
	mem(iscut, 0);
	while (!S.empty())   S.pop();
	dfs_clock = bcc_cnt = 0;
	for (int i = 1; i <= n; i++)
	if (!pre[i])         dfs(i, -1);
}

你可能感兴趣的:(无向图双连通分量)