標籤:cloc algorithm continue 無向圖 vector idg code space next
點雙和邊雙的區別我在上一篇文章中已經討論過了,這篇文章講邊雙的求法。
由於是邊雙,就決定了邊雙中一定不含有橋,但是可以含有割頂。
所以我們對邊雙唯一的限制條件就是不經過橋。
如此一來,我們可以分成兩次dfs,第一次求出所有的橋,第二次dfs時遍曆整張圖,只要保證不經過橋就可以了。
#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <stack>using namespace std;const int maxn = 105, maxm = maxn * 2;int n, m, tot, dfs_clock, bcc_cnt;int h[maxn], dfn[maxn], low[maxn], iscut[maxn], vis[maxn]; struct edge{ int v, next, isbridge;}a[maxm];vector<int> bcc[maxn];void add(int x, int y){ a[tot].v = y; a[tot].next = h[x]; h[x] = tot++;}int dfs(int u, int fa){ int lowu = dfn[u] = ++dfs_clock; int child = 0; for (int i = h[u]; ~i; i = a[i].next) { int v = a[i].v; if (!dfn[v]) { child++; int lowv = dfs(v, u); lowu = min(lowu, lowv); if (lowv >= dfn[u]) { iscut[u] = 1; } if (lowv > dfn[u]) {// printf("%d - %d\n", u, v); a[i].isbridge = 1; a[i^1].isbridge = 1; } }else if (dfn[v] < dfn[u] && v != fa) { lowu = min(lowu, dfn[v]); } } if (fa == 0 && child == 1) { iscut[u] = 0; } low[u] = lowu; return lowu;}void dfs2(int u, int fa){ bcc[bcc_cnt].push_back(u); vis[u] = 1; for (int i = h[u]; ~i; i = a[i].next) { int v = a[i].v; if (v == fa || a[i].isbridge ||vis[v]) continue; dfs2(v, u); } }int main(){ freopen("無向圖雙聯通分量.in","r",stdin); scanf("%d%d", &n, &m); memset(h, -1, sizeof h); tot = dfs_clock = 0; for (int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); add(x, y); add(y, x); } dfs(1, 0); for (int i = 1; i <= n; i++) if (!vis[i]) { bcc_cnt++; bcc[bcc_cnt].clear(); dfs2(i, 0); } for (int i = 1; i <= bcc_cnt; i++) { for (int j = 0; j < bcc[i].size(); j++) printf("%d ", bcc[i][j]); printf("\n"); } return 0;}
無向圖的雙聯通分量