• 图论--双连通分量--点双连通模板


    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<stack>
    using namespace std;
    const int maxn=1000+10;
     
    int n,m;
    int bcc_cnt;
    int dfs_clock;//bcc_cnt计数一共有多少个点-双连通分量
    int pre[maxn];
    bool iscut[maxn];
    int bccno[maxn];//bccno[i]=x表示第i个顶点属于x号点双连通分量
    vector<int> G[maxn],bcc[maxn];
    //bcc[i]中包含了i号点-双连通分量的所有节点
     
    struct Edge
    {
        int u,v;
        Edge(int u,int v):u(u),v(v){}
    };
    stack<Edge> S;
     
    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_cnt从1开始编号
                    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) //这个判断条件如果少了,就是WA,可修改POJ2942代码
            {
                S.push(e);
                lowu=min(lowu,pre[v]);
            }
        }
        if(fa<0 && child==1) iscut[u]=false;
        return lowu;
    }
     
    void find_bcc(int n)
    {
        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<n;i++)
            if(!pre[i]) dfs(i,-1);
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)==2&&n)
        {
            for(int i=0;i<n;i++) G[i].clear();
            for(int i=0;i<m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                G[u].push_back(v);
                G[v].push_back(u);
            }
            find_bcc(n);
            printf("点-双连通分量一共%d个
    ",bcc_cnt);
            for(int i=1;i<=bcc_cnt;i++)
            {
                printf("第%d个点-双连通分量包含以下点:
    ",i);
                sort(&bcc[i][0],&bcc[i][0]+bcc[i].size()); //对vector排序,使输出的点从小到大
                for(int j=0;j<bcc[i].size();j++)
                {
                    printf("%d ",bcc[i][j]);
                }
                printf("
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    [codevs]失恋28天题目系列
    [NOIP1998]最大数
    [codevs4247]奇特的生物
    [codevs1380]没有上司的舞会
    [codevs2152]滑雪
    [codevs2171]棋盘覆盖
    [codevs2170]悠闲的漫步
    [codevs1557]热浪
    [codevs1554]最佳课题选择
    nodejs建站+github page 建站问题总结
  • 原文地址:https://www.cnblogs.com/lunatic-talent/p/12798618.html
Copyright © 2020-2023  润新知