• 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;
    }

     

  • 相关阅读:
    Excelpackage的简单使用(导出用户信息并保存)
    set nocount on/off的作用,可配合存储过程使用
    在sql中case子句的两种形式
    C#开发微信门户及应用(1)--开始使用微信接口(转)
    张建总的一封信
    Jquery在线工具
    《EnterLib PIAB深入剖析》系列博文汇总 (转)
    微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART1——为什么要使用Unity? (转)
    结合领域驱动设计的SOA分布式软件架构 (转)
    ENode框架旨在帮助我们开发ddd,cqrs、eda和事件采购风格的应用程序。(netfocus 汤雪华)
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8966597.html
Copyright © 2020-2023  润新知