您的位置:首页 > 其它

点连通分量+边连通分量+割点和桥+强连通分量

2014-08-10 17:42 337 查看
老是搞不清他们的关系,不知道该用那份代码,今天理了一下,整理一下模板



点连通分量:可以求出点连通分量包含哪些点,那个点属于那个连通分量

struct edge  
{  
    int u,v;  
};  
int pre[maxn],iscut[maxn],bccno[maxn],dfs_clock,bcc_cnt;  
vector<int> G[maxn],bcc[maxn];  
stack<edge> s;  
int n;  
int dfs(int u,int fa)  
{  
    int lowu=pre[u]=++dfs_clock;  
    int child=0;  
    for(int i=0;i<G[u].size();i++)  
    {  
        int v=G[u][i];  
        edge e=edge{u,v};  
        if(!pre[v])  
        {  
            s.push(e);  
            child++;  
            int lowv=dfs(v,u);  
            lowu=min(lowu,lowv);  
            if(lowv>=pre[u])  
            {  
                iscut[u]=true;  
                bcc_cnt++;bcc[bcc_cnt].clear();  
                while(true)  
                {  
                    edge x=s.top();s.pop();  
                    if(bccno[x.u]!=bcc_cnt){bcc[bcc_cnt].push_back(x.u);bccno[x.u]=bcc_cnt;}  
                    if(bccno[x.v]!=bcc_cnt){bcc[bcc_cnt].push_back(x.v);bccno[x.v]=bcc_cnt;}  
                    if(x.u==u&&x.v==v)break;  
                }  
            }  
        }  
        else if(pre[v]<pre[u]&&v!=fa)  
        {  
            s.push(e);  
            lowu=min(lowu,pre[v]);  
        }  
    }  
    if(fa<0&&child==1)iscut[u]=0;  
    return lowu;  
}  
  
void find_bcc(int m)  
{  
    memset(pre,0,sizeof(pre));  
    memset(iscut,0,sizeof(iscut));  
    memset(bccno,0,sizeof(bccno));  
    dfs_clock=bcc_cnt=0;  
    for(int i=0;i<=m;i++)  
        if(!pre[i])dfs(i,-1);  
}


边连通分量:点连通分量是找到一个割点后,把栈里的点划分到联通分量里,而边连通分量是所有孩子处理完了,才划分

struct edge  
{  
    int u,v;  
};  
int pre[maxn],low[maxn],iscut[maxn],bccno[maxn],dfs_clock,bcc_cnt;  
int deg[maxn];  
vector<int> grid[maxn],bcc[maxn];  
stack<int> s;  
void dfs(int u,int fa)  
{  
    pre[u]=low[u]=++dfs_clock;  
    s.push(u);  
    int biao=0;  
    for(int j=0; j<grid[u].size(); j++)  
    {  
        int v=grid[u][j];  
        if(!pre[v])  
        {  
            dfs(v,u);  
            low[u]=min(low[v],low[u]);  
        }  
  
        else  if(pre[v]<pre[u]&&v!=fa)  
            low[u]=min(low[u],pre[v]);  
    }  
    if(pre[u]==low[u])  
    {  
        int j;  
        bcc_cnt++;  
        do  
        {  
            j=s.top();s.pop();  
            bccno[j]=bcc_cnt;  
        }  
        while(j!=u);  
    }  
}


割点和桥:

void dfs(int u,int fa)
{
    low[u]=pre[u]=++dfs_clock;
    int child=0;
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i];
        if(!pre[v])
        {
            child++;
            dfs(v,u);
            low[u]=min(low[v],low[u]);
            if(low[v]>=pre[u])
                iscut[u]=true;
        }
        else if(pre[v]<pre[u]&&v!=fa)
            low[u]=min(low[u],pre[v]);
    }
    if(fa<0&&child==1)iscut[u]=false;
}


有向图强连通分量:

vector<int> grid[maxn];  
int lowlink[maxn],pre[maxn],sccno[maxn],dfs_clock,scc_cnt;  
stack<int> s;  
void dfs(int u)  
{  
    pre[u]=lowlink[u]=++dfs_clock;  
    s.push(u);  
    for(int i=0;i<grid[u].size();i++)  
    {  
        int v=grid[u][i];  
        if(!pre[v])  
        {  
            dfs(v);  
            lowlink[u]=min(lowlink[u],lowlink[v]);  
        }  
        else if(!sccno[v])  
        {  
            lowlink[u]=min(lowlink[u],pre[v]);  
        }  
    }  
    if(lowlink[u]==pre[u])  
    {  
        scc_cnt++;  
        while(true)  
        {  
            int x=s.top();s.pop();  
            sccno[x]=scc_cnt;  
            if(x==u)break;  
        }  
    }  
}  
bool find_scc()  
{  
    dfs_clock=scc_cnt=0;  
    memset(sccno,0,sizeof(sccno));  
    memset(pre,0,sizeof(pre));  
    while(!s.empty())s.pop();  
    dfs(1);  
    for(int i=1;i<=n;i++)  
        if(!pre[i])dfs(i);  
    if(scc_cnt>1)return false;  
    return true;  
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: