E-DCC0分求调

P8436 【模板】边双连通分量

Prolystic @ 2024-06-06 21:01:22

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5, M = 2 * (5e6 + 5);
int n, m, num, edcc_cnt, idx = 1;
int dfn[N], low[N], blg[N], h[N];
bool brd[M];
struct Edge{
    int to, ne;
}e[M];
vector<int> edcc_ans[N];
inline int read(){
    int s = 0, w = 1;
    char ch = getchar();
    while(!isdigit(ch)) { w = (ch == '-' ? -1 : 1); ch = getchar(); }
    while(isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); }
    return s * w;
}
inline void write(int x){
    if(x < 0) { x = -x, putchar('-'); }
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
}
void init() { memset(h, -1, sizeof h); }
inline void add(int a, int b){
    e[++idx].to = b, e[idx].ne = h[a];
    h[a] = idx;
}
inline void edcc(int u, int inE){
    dfn[u] = low[u] = ++num;
    for(int i = h[u]; i != -1; i = e[i].ne){
        int v = e[i].to;
        if(!dfn[v]){
            edcc(v, i);
            low[u] = min(low[u], low[v]);
            if(low[v] > dfn[u])
                brd[i] = true;
        }else if(i != (inE ^ 1));
            low[u] = min(low[u], dfn[v]);
    }
}
inline void stn(int u){
    blg[u] = edcc_cnt;
    edcc_ans[edcc_cnt].push_back(u);
    for(int i = h[u]; i != -1; i = e[i].ne){
        int v = e[i].to;
        if((!blg[v]) && (!brd[i]))
            stn(v);
    }
}
int main(){
    n = read(), m = read();
    init();
    for(int i = 1; i <= m; i++){
        int u = read(), v = read();
        if(u == v) continue;
        add(u, v), add(v, u);
    }
    for(int i = 1; i <= n; i++)
        if(!dfn[i])
            edcc(i, -1);
    for(int i = 1; i <= n; i++){
        if(!blg[i]){
            ++edcc_cnt;
            stn(i);
        }
    }
    write(edcc_cnt), putchar('\n');
    for(int i = 1; i <= edcc_cnt; i++){
        int sz = edcc_ans[i].size();
        write(sz), putchar(' ');
        for(int j = 0; j < sz; j++)
            write(edcc_ans[i][j]), putchar(' ');
        putchar('\n');
    }
    return 0;
}

|