• 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);
            }
        }
    }
  • 相关阅读:
    如何复制保存阿里巴巴的图片。
    如何在windows2003(IIS6)下配置IIS,使其支持cshtml
    数据库字符串加法,目前没成功
    使用ASP.NET AJAX与Bootstrap 弹窗解决方案
    在MyBatis中采用模糊查询变量的引用标志应当是$而不是#
    如何让SpringBoot工程在log/控制台中实时打印MyBatis执行的SQL语句
    雇员信息完全分页方案
    将雇员信息分页显示
    把Employees显示在页面上
    给EmpMapper开放Restful接口
  • 原文地址:https://www.cnblogs.com/neopenx/p/4062182.html
Copyright © 2020-2023  润新知