求助边双连通邻接表写法正确性证明
  • 板块学术版
  • 楼主Jingyan
  • 当前回复2
  • 已保存回复2
  • 发布时间2022/8/3 20:39
  • 上次更新2023/10/27 17:09:30
查看原帖
求助边双连通邻接表写法正确性证明
557682
Jingyan楼主2022/8/3 20:39

题目是P8436,边双连通模板

代码如下

#include<bits/stdc++.h>
using namespace std;

#define PII pair<int,int>

constexpr int N=5e5+10;

int n,m,jb,cnt;
int dfn[N],low[N],fa[N],ve[N];
bool bridge[N];
vector<int> ev[N],e[N];
stack<int> st;

void tarjan(int u){
    dfn[u]=low[u]=++jb;
    st.emplace(u);

    bool flag=0;
    for(int v:e[u]){
        if(!dfn[v]){
            fa[v]=u;

            tarjan(v);
            low[u]=min(low[u],low[v]);

            if(low[u]>dfn[u])
                bridge[v]=1;
        }
        else if(v!=fa[u] || flag)
            low[u]=min(low[u],dfn[v]);
        else
            flag=1;
    }

    if(dfn[u]==low[u]){
        ve[u]=++cnt,ev[cnt].emplace_back(u);

        while(st.top()!=u)
            ev[cnt].emplace_back(st.top()),
            ve[st.top()]=cnt,st.pop();

        st.pop();
    }
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);

    cin>>n>>m;

    int a,b;
    for(int i=0;i<m;i++){
        cin>>a>>b;
        e[a].emplace_back(b),e[b].emplace_back(a);
    }
        

    for(int i=1;i<=n;i++)
        if(!dfn[i])
            tarjan(i);
    
    cout<<cnt<<endl;

    for(int i=1;i<=cnt;i++){
        cout<<ev[i].size()<<' ';
        for(int j:ev[i])
            cout<<j<<' ';
        cout<<endl;
    }

    return 0;
}

tagjan函数中定义flag用来处理重边的特殊情况,避免仅判断v!=fa[u]导致的WA,不明白这个写法思路为什么成立,但是本人蒟蒻又没有能力hack这个写法,只能求助各位神犇帮忙hack掉或者是证明这个写法的正确性(思路不源于本人,代码是本人的)

2022/8/3 20:39
加载中...