码迷,mamicode.com
首页 > 移动开发 > 详细

边双联通分量

时间:2018-01-21 19:21:22      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:key   printf   +=   perl   return   algo   clu   size   tarjan   

#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define maxn 1005
#define maxm 1000005

using namespace std;

struct Edge{
    int u,v;
    Edge(int u=0,int v=0):u(u),v(v){}
}e[maxm];
int n,m,stamp,dfn[maxn],low[maxn],bccno[maxn],bcc_cnt;
vector<int> vec[maxn];
bool isbridge[maxm];

void tarjan(int index,int fa)
{
    int tmp;
    dfn[index]=low[index]=++stamp;
    for(int i=0;i<vec[index].size();i++)
    {
        tmp=e[vec[index][i]].v;
        if(!dfn[tmp])
        {
            tarjan(tmp,index);
            low[index]=min(low[index],low[tmp]);
            if(low[tmp]>dfn[index])
                isbridge[vec[index][i]]=isbridge[vec[index][i]^1]=1;
        }
        else if(dfn[tmp]<dfn[index] && tmp!=fa)
        {
            low[index]=min(low[index], dfn[tmp]);
        }
    }
}

void dfs(int index)
{
    dfn[index]=1;
    bccno[index]=bcc_cnt;
    for(int i=0;i<vec[index].size();i++)
    {
        int tmp=vec[index][i];
        if(isbridge[tmp])
            continue;
        if(!dfn[e[tmp].v])
        {
            dfs(e[tmp].v);
        }
    }
}

void find_ebcc(){
    bcc_cnt=stamp=0;
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(bccno,0,sizeof(bccno));
    memset(isbridge,0,sizeof(isbridge));
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            tarjan(i, -1);
    memset(dfn,0,sizeof(dfn));
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
        {
            bcc_cnt++;
            dfs(i);
        }
    }               
}

int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        memset(vec,0,sizeof(vec));
        int x,y;
        for(int i=0;i<m;i++)
        {
            scanf("%d %d",&x,&y);
            e[i*2]=Edge(x,y);
            vec[x].push_back(2*i);
            e[i*2+1]=Edge(y,x);
            vec[y].push_back(2*i+1);
        }
        find_ebcc();

        if(bcc_cnt==1)
            printf("0\n");
        else
        {
            memset(dfn,0,sizeof(dfn));
            for(int i=0;i<m*2;i+=2)
            {
                x=e[i].u, y=e[i].v;
                if(bccno[x]!=bccno[y])
                {
                    dfn[bccno[x]]++;
                    dfn[bccno[y]]++;
                }
            }

            int a=0,b=0;
            for(int i=1;i<=bcc_cnt;i++)
            {
                if(dfn[i]==0)
                    a++;
                if(dfn[i]==1)
                    b++;
            }

            printf("%d\n",a+(b+1)/2);           
        }
    }

    return 0;
}

边双联通分量

标签:key   printf   +=   perl   return   algo   clu   size   tarjan   

原文地址:https://www.cnblogs.com/lmjer/p/8324770.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!