You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
2.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
//此题是P8436的弱化版本弱化了记录每个边双中点有哪些:vector<int> belong[N];
const int N = 500010, M = 2000010 * 2;
int n, m;
int dfn[N], low[N], ts, stk[N], top;
vector<int> belong[N]; //边双中有哪些原始点
int id[N], dcc_cnt; //原始点x属于哪个边双连通分量dcc_cnt指边双连通分量个数
int is_bridge[M]; //记录哪些边是割边
//链式前向星
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++;
}
//边双连通分量
void tarjan(int u, int fa) {
dfn[u] = low[u] = ++ts;
stk[++top] = u;
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (!dfn[j]) {
tarjan(j, i);
low[u] = min(low[u], low[j]);
if (dfn[u] < low[j]) is_bridge[i] = is_bridge[i ^ 1] = true; //记录割边
} else if (i != (fa ^ 1))
low[u] = min(low[u], dfn[j]);
}
if (dfn[u] == low[u]) {
++dcc_cnt; //边双数量+1
int x;
do {
x = stk[top--];
id[x] = dcc_cnt; // 记录点与边双关系
belong[dcc_cnt].push_back(x); // 记录边双中有哪些点
} while (x != u);
}
}
int main() {
scanf("%d %d", &n, &m);
memset(h, -1, sizeof h);
for (int i = 0; i < m; i++) {
int a, b;
scanf("%d %d", &a, &b);
add(a, b), add(b, a);
}
for (int i = 1; i <= n; i++)
if (!dfn[i]) tarjan(i, -1);
//输出边双个数
printf("%d\n", dcc_cnt);
// for (int i = 1; i <= dcc_cnt; i++) {
// //此边双中点的数量
// printf("%d ", belong[i].size());
// //此边双中都有哪些点
// for (int j = 0; j < belong[i].size(); j++)
// printf("%d ", belong[i][j]);
// puts("");
// }
return 0;
}