标签:图的连通性 图论 无向图的边-双连通分量
/*========================================= 无向图求点-双连通分量 (任意两个点之间至少存在两条“点不重复”的路径) 复杂度: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