进食后人(关于vector神教

P8436 【模板】边双连通分量

mountain_climber @ 2024-10-21 14:26:59

可能会有重边。

如果写Vector可以考虑使用以下方法:

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
inline int read(){
    char ch=getchar();int x=0,f=1;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void write(int x){
    if(x<0){x=~(x-1);putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
int n,m;
int dfn[N],low[N],dfncnt=0,fatr[N];
bool flg[N]={false},flg1[N]={false};
int edcc[N],tot=0;//edcc表示i所处的边双的编号,tot表示一共有多少个边双
vector<int> g[N],ans[N];
vector<int> id[N];
inline void tarjan(int u,int fa,int idx){
    dfn[u]=low[u]=++dfncnt;
    fatr[u]=fa;
    for(int i=0;i<g[u].size();i++){
        int v=g[u][i];
        if(!dfn[v]){
            tarjan(v,u,id[u][i]);
            low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u]){
                flg[v]=true;
                flg1[v]=true;
            }
        }
        else if(dfn[v]&&(v!=fa||i!=idx)){
            low[u]=min(low[u],dfn[v]);
        }
    }
}
inline void dfs(int now){
    edcc[now]=tot;
    ans[tot].push_back(now);
    for(auto v:g[now]){
        if(((fatr[now]==v&&flg[now])||(fatr[v]==now&&flg[v]))||edcc[v]){
            continue;
        }
        dfs(v);
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL),cout.tie(NULL);
    n=read(),m=read();
    for(int i=1;i<=m;i++){
        int u,v;
        u=read(),v=read();
        g[u].push_back(v);
        g[v].push_back(u);
        id[u].push_back(g[v].size()-1);
        id[v].push_back(g[u].size()-1);
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i]){
            tarjan(i,i,-1);
        }
    }
    for(int i=1;i<=n;i++){
        if(!edcc[i]){
            // cout<<'!'<<i<<'\n';
            ++tot;
            dfs(i);
        }
    }
    // for(int i=1;i<=n;i++){
    //     if(flg1[i]){
    //         cout<<fatr[i]<<'-'<<i<<'\n';
    //     }
    // }
    write(tot);puts("");
    for(int i=1;i<=tot;i++){
        write(ans[i].size());printf(" ");
        for(auto j:ans[i]){
            write(j);printf(" ");
        }
        puts("");
    }
    return 0;
}
//100pts,神秘id记录法直接不带log

本质上是把重边的节点重复跑,从而让其无法成为割边。


|