In an undirected graph, the edge-two-connected component the two-connected component of an undirected graph actually contains two parts: vertex-two-connected component and edge-two-connected component.
Point-Connected ComponentIt refers to the path (excluding the start point and end point) in the connected component where multiple points do not overlap between any two points)
Edge-Connected ComponentIt refers to the path with multiple edges between any two points in the connected component.
When solving
Point-Connected ComponentIt does not matter whether the undirected graph has duplicate edges, because a vertex can only go through one time (it does not matter if there is duplicate edges). This article does not discuss vertices in depth-Dual-connected components, code is provided for reference: (you can also take a look at the poj2942 question and solve the problem report)
/* ===================================================== === Undirected graph for vertex-dual connected component (at least two "non-repeating vertices" paths exist between any two vertices) complexity: O (E + V) pushes each edge to the stack during the cut point process. When it comes to the cut point, it pops all the edges, until (u, v) is met, each connected component has a duplicate edge in BCC [CNT]. // It doesn't matter if there is any duplicate edge (because one point can only go through once) ========================================================== = */const int maxn = 1100; int bccno [maxn], dfn [maxn], low [maxn], CNT, N; // Where the cut point bccno [] Meaningless bool cut [maxn]; int dfs_clock; vector <int> G [maxn], bcc [maxn]; struct edge {int U, V; e DGE (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 starts from 1! While (1) {edge x = S. Top (); S. Pop (); If (bccno [X. u]! = CNT) BCC [CNT]. push_back (X. u), bccno [X. u] = CNT; // The points in each vertex-two-connected component are saved here (if you want to save the edge, you need to modify it) 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 );}
When solving
Edge-Connected ComponentA lot of online code is wrong! The correct method is to perform a DFS operation on the source image, find the cut edge, and mark it. Then, DFS finds each connected component again (because each connected component is separated by the bridge). For the edge-double connected component, if there is any duplicate edge in a graph, the result will be affected. For example, a graph without a duplicate edge: 1 --- 2 (with two sides-Connected Component) a graph with a duplicate edge: 1 ---- 2 (with a duplicate edge between 1 and 2) there is only one edge-connected component.
1. Do not consider duplicate edges first. You may find some code on the Internet. by performing a DFS operation on the source image, you can get the same low [] value for all edge-Dual-connected components. In fact, this method is wrong, because when there are two or more rings in a connected component, the code will be faulty. For example, this group of data: 16 21
1 8
1 7
1 6
1 2
1 9
9 16
9 15
9 14
9 10
10 11
11 13
11 12
12 13
11 14
15 16
2 3
3 5
3 4
4 5
3 6
7 8
The answer obtained using the above method is 0, which is actually 1.
Therefore, when solving edge-Dual-connected components, you must first obtain the cut edge and then DFS.
2. If an undirected graph has a duplicate edge, you cannot use a vector to store the edge and use an adjacent table to store the edge. The method is similar to that of creating an edge in a network flow. Create a forward edge I and a reverse edge I ^ 1. This ensures that the duplicate edge can be processed. The specific code is as follows: You can refer to poj 3352 (no duplicate edge) and 3177 (with duplicate edge) (unfortunately, the data on both questions is not strong)
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);}
Edge of an undirected graph in poj 3352 & 3177-connected component (Without Duplicate edge and duplicate edge)