zoukankan      html  css  js  c++  java
  • POJ 2117 (割点+连通分量)

    题目链接http://poj.org/problem?id=2117

    题目大意:在一个非连通图中,求一个切除图中任意一个割点方案,使得图中连通分量数最大。

    解题思路

    一个大陷阱,m可以等于0,这时候要特判,结果就是n-1。

    同时出题者脑子秀逗了,也不给C的范围。我开了两倍点大小RE了,于是怒开了五倍点大小才A了。

    本题不是连通图,需要先计算原始图中的连通分量。方法就是dfs染色。

    然后dfs求割点。

    之后枚举割点,由于是非连通图,所以连通分量数=原始分量数+block-1。

    -1的原因是,每次相当于对其中一个连通分量计算,加上新的block之后,所以要减-1。

    #include "cstdio"
    #include "cstring"
    #include "vector"
    using namespace std;
    #define maxn 10005
    struct Edge
    {
        int to,next;
    }e[maxn*5];
    int dfs_clock,pre[maxn],block,head[maxn],tol;
    bool cut[maxn],vis[maxn];
    void addedge(int u,int v)
    {
        e[tol].to=v;
        e[tol].next=head[u];
        head[u]=tol++;
    }
    int dfs(int u,int fa)
    {
        int lowu=pre[u]=++dfs_clock;
        int child=0;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            if(!pre[v])
            {
                int lowv=dfs(v,u);
                lowu=min(lowu,lowv);
                if(lowv>=pre[u]) cut[u]=true;
            }
            else if(pre[v]<pre[u]&&v!=fa) lowu=min(lowu,pre[v]);
        }
        if(fa<0&&child==1) cut[u]=false;
        return lowu;
    }
    void check(int u,int fa)
    {
        vis[u]=true;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            if(!vis[v])
            {
                if(u==fa) block++;
                check(v,fa);
            }
        }
    }
    void link(int u) //判断初始连通分量
    {
        vis[u]=true;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            if(!vis[v]) link(v);
        }
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int n,m,u,v;
        while(scanf("%d%d",&n,&m)&&n)
        {
            memset(head,-1,sizeof(head));
            memset(pre,0,sizeof(pre));
            memset(cut,false,sizeof(cut));
            dfs_clock=0;tol=0;
            if(m==0) printf("%d
    ",n-1); //特判
            else
            {
                for(int i=1; i<=m; i++)
                {
                    scanf("%d%d",&u,&v);
                    addedge(u,v);
                    addedge(v,u);
                }
                int res=0,tt=0;
                for(int i=0; i<n; i++) if(!vis[i]) {tt++;link(i);}
                memset(vis,false,sizeof(vis));
                for(int i=0; i<n; i++) if(!pre[i])  dfs(i,-1);
                res=tt;
                for(int i=0; i<n; i++)
                {
                    if(cut[i])
                    {
                        check(i,i);
                        if(tt) res=max(res,block+tt-1);
                        block=0;
                        memset(vis,false,sizeof(vis));
                    }
                }
                printf("%d
    ",res);
            }
        }
    }
  • 相关阅读:
    团队冲刺六
    团队冲刺五
    【Mybaits学习】03_ CRUD基于注解
    【Mybaits学习】02_ 快速入门
    【Mybaits学习】01_ 初识
    深圳国际马拉松
    深圳南山半程马拉松
    Selenide使用笔记
    UI自动化测试01-环境搭建
    Java C3p0在Spring中运用
  • 原文地址:https://www.cnblogs.com/neopenx/p/4062182.html
Copyright © 2011-2022 走看看