Files
python/TangDou/AcWing/DCC/Backup/P8435_vBcc_1.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

75 lines
2.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10, M = 4e6 + 10;
//链式前向星
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c = 0) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
//点双需要的变量
int dfn[N], low[N], stk[N], timestamp, top;
vector<int> bcc[N];
int bcnt;
//点双模板1 【推荐】
void tarjan(int u, int fa) {
low[u] = dfn[u] = ++timestamp;
stk[++top] = u;
int son = 0; //子节点个数
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
// if (j == fa) continue; //这句看似无用,dfn[j]可以包含,但事实证明,有些题会在后面加入其它代码造成执行逻辑错误,背模板时,加上这句保准!
if (!dfn[j]) {
son++; //找到一个子节点
tarjan(j, u);
low[u] = min(low[u], low[j]);
if (low[j] >= dfn[u]) {
int x;
bcnt++;
do {
x = stk[top--];
bcc[bcnt].push_back(x);
} while (x != j); //将子树出栈
bcc[bcnt].push_back(u); //把割点/树根也丢到点双里
}
} else
low[u] = min(low[u], dfn[j]);
}
//特判独立点
if (fa == -1 && son == 0) bcc[++bcnt].push_back(u);
}
int n, m;
int main() {
//文件输入输出
#ifndef ONLINE_JUDGE
freopen("P8435.in", "r", stdin);
#endif
//清空链式前向星
memset(h, -1, sizeof h);
scanf("%d %d", &n, &m);
while (m--) {
int a, b;
scanf("%d %d", &a, &b);
if (a != b) add(a, b), add(b, a); //此题目需要判断一下自环,否则1和11会挂
}
//给定一个n个点m条边的无向图,求该图中的所有点双连通分量(v-bcc)
for (int i = 1; i <= n; i++) //每个点做为根结点进行枚举
if (!dfn[i]) tarjan(i, -1);
printf("%d\n", bcnt);
for (int i = 1; i <= bcnt; i++) { //枚举每个双连通分量
printf("%d ", bcc[i].size());
for (int j = 0; j < bcc[i].size(); j++) //输出双连通分量中的点有哪些
printf("%d ", bcc[i][j]);
puts("");
}
return 0;
}