边双连通分量
我们令双连通表示两个节点之间段开一条边还是连通的。
边双连通分量 表示求出几个最大的点集, 使得任意一个点集中点两两双连通。
例题 luoguP8436
方法1
我们发现, 如果两个节点原先连通但不是双连通, 肯定他们之间的路径是经过某一座桥, 所以可以求出来桥, 把桥拆掉, 再求连通块。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e6 + 5;
struct Edge{
int v, w;
};
int tot, cnt, cn[N], dfn[N], low[N], vis[N], n, m, u, v;
vector<Edge>g[N];
vector<int>e[N];
void dfs(int x, int f){
dfn[x] = low[x] = ++cnt;
for(auto [v, w] : g[x]){
if(!dfn[v]){
dfs(v, w);
low[x] = min(low[x], low[v]);
}
else if(w != f){
low[x] = min(low[x], dfn[v]);
}
}
if(low[x] == dfn[x]){
vis[f] = 1;
}
}
void DFS(int x){
if(cn[x]){
return;
}
cn[x] = 1;
e[tot].push_back(x);
for(auto [v, w] : g[x]){
if(!vis[w]){
DFS(v);
}
}
}
int main(){
cin >> n >> m;
for(int i = 1; i <= m; ++i){
cin >> u >> v;
g[u].push_back({v, i});
g[v].push_back({u, i});
}
for(int i = 1; i <= n; ++i){
if(!dfn[i]){
dfs(i, 0);
}
}
for(int i = 1; i <= n; ++i){
if(!cn[i]){
++tot;
DFS(i);
}
}
cout << tot << '\n';
for(int i = 1; i <= tot; ++i){
cout << e[i].size() << ' ';
for(auto x : e[i]){
cout << x << ' ';
}
cout << '\n';
}
return 0;
}
方法2
未完工 \(\cdots\)
标签:连通,cn,边双,int,dfn,low,分量 From: https://www.cnblogs.com/liuyichen0401/p/18124179