• BZOJ2730: [HNOI2012]矿场搭建


    【传送门:BZOJ2730


    简要题意:

      给出m条无向边,每个点有人,有时候会出现一个点崩塌,使得这个点和与这个点相连的边都不能经过

      可以在某些点设置安全出口,其它可以到达这些点的点上的人可以逃出去

      请问至少设置多少个安全出口和求出最少安全出口的情况下有多少种设置的方案


    题解:

      Tarjan求割点例题

      设n为点数,n直接等于所有边中找出最大的点

      题目中只会出现一个点崩塌

      先找出所有割点,然后求出删除了割点之后的所有连通块与多少个割点相连

      设num为安全出口数,ans为方案数,tot为当前连通块的点数

      对于一个连通块

      如果不与其它割点相连,num+=2,ans*=(tot-1)*tot/2

      如果只与一个割点相连,num+=1,ans*=tot

      如果与两个及以上割点相连,则不处理,因为即使其中一个割点崩塌,这个连通块的点依旧可以通过其它割点走向其它连通块的出口

      特判一下,如果整个图都没有割点,则num=2,ans=n*(n-1)/2


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    struct node
    {
        int x,y,next;
    }a[1100];int len,last[510];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    int dfn[510],low[510],id;
    bool v[510];
    int rt,cnt;
    void findcut(int x)
    {
        dfn[x]=low[x]=++id;
        int t=0;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(dfn[y]==0)
            {
                t++;
                findcut(y);
                if(low[y]>=dfn[x]) v[x]=true,cnt++;
            }
            low[x]=min(low[x],low[y]);
        }
        if(x==rt&&t==1) v[x]=false,cnt--;
    }
    int tot;
    void dfs(int x,int t)
    {
        dfn[x]=t;
        if(v[x]==true){cnt++;return ;}
        tot++;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(dfn[y]!=t)
            {
                dfs(y,t);
            }
        }
    }
    int main()
    {
        int n,m;int T=0;
        while(scanf("%d",&m)!=EOF)
        {
            if(m==0) break;T++;
            len=0;memset(last,0,sizeof(last));
            n=0;
            for(int i=1;i<=m;i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                ins(x,y);ins(y,x);
                n=max(n,max(x,y));
            }
            id=cnt=0;
            memset(dfn,0,sizeof(dfn));
            memset(low,0,sizeof(low));
            memset(v,false,sizeof(v));
            for(int i=1;i<=n;i++)
            {
                rt=i;
                if(dfn[i]==0) findcut(i);
            }
            if(cnt==0) printf("Case %d: 2 %d
    ",T,n*(n-1)/2);
            else
            {
                id=0;
                memset(dfn,0,sizeof(dfn));
                int num=0;LL ans=1;
                for(int i=1;i<=n;i++)
                {
                    if(dfn[i]==0&&v[i]==false)
                    {
                        tot=cnt=0;
                        dfs(i,i);
                        if(cnt==0) num+=2,ans*=LL((tot-1)*tot/2);
                        if(cnt==1) num+=1,ans*=LL(tot);
                    }
                }
                printf("Case %d: %d %lld
    ",T,num,ans);
            }
        }
        return 0;
    }

     

  • 相关阅读:
    vue集成百度UEditor富文本编辑器
    HTTPS访问站点,出现证书问题解决(转载) 规格严格
    JSSE 提供的 动态 debug 追踪模式 规格严格
    javax.net.debug 规格严格
    Oralce null 规格严格
    pipe 规格严格
    (总结)ibatis 动态传入表名和列名 规格严格
    垃圾回收算法简介 规格严格
    转载(正则表达式的分类) 规格严格
    长度为0的数组 规格严格
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8966597.html
Copyright © 2020-2023  润新知