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

70 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, root;
vector<int> bcc[N];
int bcnt;
//点双模板2 【不推荐】
void tarjan(int u) {
dfn[u] = low[u] = ++timestamp; //分配时间戳
stk[++top] = u; // u入栈
for (int i = h[u]; ~i; i = ne[i]) { //枚举u的每条边
int j = e[i];
if (!dfn[j]) { //如果j没有被走过
tarjan(j); // dfs
low[u] = min(low[u], low[j]); //用儿子的low[j]尝试更新low[u]
if (low[j] >= dfn[u]) { //如果u是割点
bcnt++; //连通块增加
int x; //利用栈,维护此连通块中所有的点
do {
x = stk[top--];
bcc[bcnt].push_back(x);
} while (x != j);
bcc[bcnt].push_back(u); // u是割点,也必须属于其它连通块,不能用了拉倒,需要再次入栈
}
} else
low[u] = min(low[u], dfn[j]);
}
//特判独立点
if (u == root && h[u] == -1) 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);
for (int i = 0; i < m; i++) {
int a, b;
scanf("%d %d", &a, &b);
if (a != b) add(a, b), add(b, a); //此题目需要判断一下自环,否则1和11会挂
}
//给定一个n个点m条边的无向图,求该图中的所有点双连通分量(v-bcc)
for (root = 1; root <= n; root++) //每个点做为根结点进行枚举
if (!dfn[root]) tarjan(root);
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;
}