tarjan算法之 边双连通分量

边双连通分量:对于一个无向图的子图,当删除其中任意一条边后,不改变图内点的连通性,这样的子图叫做边的双连通子图。而当子图的边数达到最大时,叫做边的双连通分量


我们要求边双连通分量,思路是把图中的所有桥都删去,然后剩下的每一个区域就是一个双连通分量


具体做法还是利用tarjan算法,,我们要维护一个stack来统计出每一个双连通分量的所有结点

#pragma warning(disable:4996)
#include <cstdio>
#include <stack>
#include <vector>
#include <cstring>
#include <algorithm>
#define N 20010
using namespace std;

vector<int>to[N];
//father是标记数组,0的时候表示根节点,-1表示为访问过,其他表示父节点
int ans[N], father[N];
int dfn[N], low[N], cnt, dfs_clock;
stack<int>s;

void init(){
	memset(father, -1, sizeof father);
	father[1] = 0;
	cnt = 0;
	dfs_clock = 0;
	while (!s.empty())s.pop();
}

void add(int u, int v){
	to[u].push_back(v);
}

void dfs(int u){
	dfn[u] = low[u] = ++dfs_clock;
	s.push(u);

	for (int i = 0; i < (int)to[u].size(); i++){
		int v = to[u][i];

		//如果 v 未访问过
		if (father[v] == -1){
			father[v] = u;
			dfs(v);
			low[u] = min(low[u], low[v]);
		}
		//访问过 v,但 v 不是 u 的父亲结点
		else if (father[u] != v){
			low[u] = min(low[u], dfn[v]);
		}
	}

	//边(father[u],u)是桥
	// 因为low[u] == dfn[u],对(parent[u],u)来说有dfn[u] > dfn[ parent[u] ],因此low[u] > dfn[ parent[u] ]
	// 所以(parent[u],u)一定是一个桥,那么此时栈内在u之前入栈的点和u被该桥分割开
	// 则u和之后入栈的节点属于同一个组
	//将从u到栈顶所有的元素标记为一个组,并弹出这些元素。
	if (dfn[u] == low[u]){
		//这里是对连通分量的操作了


		/*vector<int>vec;
		int id = u;
		int now = s.top();
		while (now != u){
			vec.push_back(now);
			s.pop();
			id = min(id, now);
			now = s.top();
		}
		vec.push_back(now); s.pop();
		for (int i = 0; i < vec.size(); i++){
			ans[vec[i]] = id;
		}
		cnt++;*/
	}

}


你可能感兴趣的:(tarjan算法之 边双连通分量)