标签:图的连通性 图论 无向图的边-双连通分量
/*=========================================
无向图求点-双连通分量 (任意两个点之间至少存在两条“点不重复”的路径)
复杂度:O(E + V)
在做割点的过程中,将每条边push进栈,当碰到割点的时候,将所有的边pop出来,直到遇到(u,v)为止
每个连通分量存在bcc[cnt]中
//有没有重边无所谓(因为一个点只能经过一次)
=========================================*/
const int maxn = 1100;
int bccno[maxn], dfn[maxn], low[maxn], cnt, n; //其中割点的bccno[]无意义
bool cut[maxn];
int dfs_clock;
vector<int> g[maxn], bcc[maxn];
struct edge {
int u, v;
edge(int _u, int _v) {
u = _u, v = _v;
}
};
stack<edge> s;
void dfs(int u, int f) {
low[u] = dfn[u] = ++dfs_clock;
int child = 0;
for (int i = 0; i < g[u].size(); i++) if (g[u][i] != f) {
int v = g[u][i];
edge e(u, v);
if (!dfn[v]) {
s.push(e);
dfs(v, u);
child++;
if (low[v] < low[u]) low[u] = low[v];
if (low[v] >= dfn[u]) {
cut[u] = true;
cnt++;
bcc[cnt].clear(); //cnt从1开始!
while(1) {
edge x = s.top();
s.pop();
if (bccno[x.u] != cnt) bcc[cnt].push_back(x.u), bccno[x.u] = cnt; //这里存的是每个点-双连通分量里的点(如果要存边需要修改)
if (bccno[x.v] != cnt) bcc[cnt].push_back(x.v), bccno[x.v] = cnt;
if (x.u == u && x.v == v) break;
}
}
}
else if (dfn[v] < low[u]) {
s.push(e);
low[u] = dfn[v];
}
}
if (f == -1 && child < 2) cut[u] = false;
}
void find_bcc(int n) {
memset(dfn, 0, sizeof(dfn));
memset(cut, 0, sizeof(cut));
memset(bccno, 0, sizeof(bccno));
while(!s.empty()) s.pop();
dfs_clock = cnt = 0;
for (int i = 1; i <= n; i++) if (!dfn[i]) dfs(i, -1);
}const int maxn = 5100;
const int maxm = 10100;
int g[maxn], n, m;
int bccno[maxn], dfn[maxn], low[maxn], bcc_cnt, dfs_clock, cnt;
bool vis[maxm * 2], isbridge[maxm * 2];
struct node {
int v, nxt;
} e[maxm * 2];
void add(int u, int v) {
e[++cnt].v = v;
e[cnt].nxt = g[u];
g[u] = cnt;
e[++cnt].v = u;
e[cnt].nxt = g[v];
g[v] = cnt;
}
void init() {
cnt = 1;
memset(g, 0, sizeof(int) * (n + 10));
int u, v;
for (int i = 0; i < m; i++) {
scanf("%d%d", &u, &v);
add(u, v);
}
}
void dfs(int u) {
dfn[u] = low[u] = ++dfs_clock;
for (int i = g[u]; i; i = e[i].nxt) {
int v = e[i].v;
if (!dfn[v]) {
vis[i] = vis[i ^ 1] = true;
dfs(v);
low[u] = min(low[v], low[u]);
if (low[v] > dfn[u]) isbridge[i] = isbridge[i ^ 1] = true;
} else if (dfn[v] < dfn[u] && !vis[i]) {
vis[i] = vis[i ^ 1] = true;
low[u] = min(low[u], dfn[v]);
}
}
}
void dfs_bcc(int u, int id) {
bccno[u] = id;
for (int i = g[u]; i; i = e[i].nxt) if (!isbridge[i]) {
int v = e[i].v;
if (!bccno[v]) dfs_bcc(v, id);
}
}
void find_bcc(int n) {
dfs_clock = bcc_cnt = 0;
memset(dfn, 0, sizeof(dfn));
memset(bccno, 0, sizeof(bccno));
memset(vis, 0, sizeof(vis));
memset(isbridge, 0, sizeof(isbridge));
for (int i = 1; i <= n; i++) if (!dfn[i]) dfs(i);
for (int i = 1; i <= n; i++) if (!bccno[i]) dfs_bcc(i, ++bcc_cnt);
}POJ 3352 & 3177 无向图的边-双连通分量(无重边 & 重边)
标签:图的连通性 图论 无向图的边-双连通分量
原文地址:http://blog.csdn.net/sio__five/article/details/38984843