0pts求调玄关

P8436 【模板】边双连通分量

sunqihuan @ 2024-12-13 22:14:18

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5,M=2e6+5;
int n,m,h[N],e[M],ne[M],idx;
int dfn[N],low[N],num,st[N],top;
int dcc,bridge[M],vis[N];
vector<int> ans[N];
void add(int u,int v){
    e[idx]=v;
    ne[idx]=h[u];
    h[u]=idx++;
}
void tarjan(int u,int fa){
    dfn[u]=low[u]=++num;
    st[++top]=u;
    for(int i=h[u];i!=-1;i=ne[i]){
        int v=e[i];
        if(!dfn[v]){
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(dfn[u]<low[v]){
                bridge[i]=bridge[i^1]=1;
            }
        }else if(i!=(fa^1)){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u]){
        dcc++;
        int now;
        do{
            now=st[top--];
            ans[dcc].push_back(now);
        }while(now!=u);
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    memset(h,-1,sizeof(h));
    while(m--){
        int u,v;
        cin>>u>>v;
        add(u,v);
        add(v,u);
    }
    for(int i=1;i<=n;i++){
        if(dfn[i]==0)tarjan(i,-1);
    }
    cout<<dcc<<endl;
    for(int i=1;i<=dcc;i++){
        cout<<ans[i].size()<<" ";
        for(int j=0;j<ans[i].size();j++)cout<<ans[i][j]<<" ";
        cout<<endl;
    }
    return 0;
}

by yinbe2 @ 2024-12-14 16:11:44

@sunqihuan你的代码好像是点双吧


by yinbe2 @ 2024-12-14 16:13:29

    if(dfn[u]==low[u]){
        dcc++;
        int now;
        do{
            now=st[top--];
            ans[dcc].push_back(now);
        }while(now!=u);
    }

这是点双的求法


by yinbe2 @ 2024-12-14 16:14:45

边双只需要找出所有的桥后忽略所有的桥,然后进行DFS就好了


by sunqihuan @ 2024-12-14 18:05:41

同志,我没法互关你,因为早就关过了……


|