边的双联通分量

来源:互联网 发布:aconex是什么软件 编辑:程序博客网 时间:2024/04/29 21:19

//其实边的双联通分量, 就是无向图的强联通分量, 所以缩点就是可以直接套强联通分量的缩点板子.
//最多由于题意的不同, 在缩点是进行的操作不同.

解释版:

void tarjan(int fa,int u){    dfn[u]=low[u]=cnt++;    s.push(u);    for(int i=0;i<G[u].size();i++){        int nex = G[u][i];        if(nex == fa) continue;  //就是之前下来的那条边,这个是不能算在low中的,否则low就没有意义//了,所以要continue. 并且由于给出的顺序问题,又是必须要记双向边的,所以就是要这样做啦.        if(!dfn[nex]){            tarjan(u,nex);            low[u]=min(low[u],low[nex]);        }        else low[u]=min(low[u],dfn[nex]);  //儿子经过的地方, 父亲也是经过这里.    }    if(low[u]==dfn[u]){   //边的双联通分量一定在环内, 所以走到环的时候再进行转换.        res++;        while(1){            int v=s.top();            s.pop();            minn[res] = min(minn[res],v);            bel[v] = res;            if(v == u) break;        }    }}     //res双联通的个数.

模板理解题
//就是要满足题目要求很烦.

/** @Cain*/const int maxn=1e5+10;int n,m;int res,cnt;vector<int>G[maxn];stack<int>s;int dfn[maxn];int low[maxn];int minn[maxn];int bel[maxn];bool vis[maxn];void init(){    Fill(dfn,0);    Fill(low,0);    Fill(bel,0);    Fill(vis,false);    res = 0;    cnt = 1;    for(int i=0;i<=n;i++)        minn[i] = inf;}void tarjan(int fa,int u){    dfn[u]=low[u]=cnt++;    s.push(u);    for(int i=0;i<G[u].size();i++){        int nex = G[u][i];        if(nex == fa) continue;        if(!dfn[nex]){            tarjan(u,nex);            low[u]=min(low[u],low[nex]);        }        else low[u]=min(low[u],dfn[nex]);  //儿子经过的地方, 父亲也是经过这里.    }    if(low[u]==dfn[u]){   //边的双联通分量一定在环内, 所以走到环的时候再进行转换.        res++;        while(1){            int v=s.top();            s.pop();            minn[res] = min(minn[res],v);            bel[v] = res;            if(v == u) break;        }    }}void solve(){    scanf("%d%d",&n,&m); //因为不知道起点, 所以还要加双向边.    init();    for(int i=1;i<=m;i++){        int u,v;        scanf("%d%d",&u,&v);        G[u].push_back(v);        G[v].push_back(u);    }    tarjan(1,-1);    printf("%d\n",res);    for(int i=1;i<=n;i++){        printf("%d%c",minn[bel[i]],i==n? '\n' :' ');    }}int main(){    int t = 1 ;    //scanf("%d",&t);    while(t--){    //    printf("Case %d: ", cas++);        solve();        //printf("\n");    }}
原创粉丝点击