zoukankan      html  css  js  c++  java
  • codevs 1996 矿场搭建

    1996 矿场搭建

     

     时间限制: 1 s
     空间限制: 256000 KB
     题目等级 : 大师 Master
     
     
    题目描述 Description

    煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。
    请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。

    输入描述 Input Description

    输入文件有若干组数据,每组数据的第一行是一个正整数N(N≤500),表示工地的隧道数,接下来的N 行每行是用空格隔开的两个整数S 和T,表示挖煤点S 与挖煤点T 由隧道直接连接。输入数据以0 结尾。

    输出描述 Output Description

    输入文件中有多少组数据,输出文件中就有多少行。每行对应一组输入数据的结果。其中第i 行以Case i: 开始(注意大小写,Case 与i 之间有空格,i 与:之间无空格,:之后有空格),其后是用空格隔开的两个正整数,第一个正整数表示对于第i 组输入数据至少需要设置几个救援出口,第二个正整数表示对于第i 组输入数据不同最少救援出口的设置方案总数。输入数据保证答案小于2^64。输出格式参照以下输入输出样例。

    样例输入 Sample Input

    9
    1 3
    4 1
    3 5
    1 2
    2 6
    1 5
    6 3
    1 6
    3 2
    6
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    0

    样例输出 Sample Output

    Case 1: 2 4
    Case 2: 4 1

    数据范围及提示 Data Size & Hint

    Case 1 的四组解分别是(2,4),(3,4),(4,5),(4,6);
    Case 2 的一组解为(4,5,6,7)。

    /*
    额 刚开始求得缩点后度为1的结果不对
    比如 缩完点后只有一个点等
    正解
    先求出割点 割点将其他的分成很多部分
    这些部分
    连着2个以上割点的不用建 
    连着1个割点的要建一个
    连着0个割点的要建两个 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define LL long long
    #define maxn 510
    using namespace std;
    LL n,m,topt,tot,anst,answ,sum;
    LL first[maxn];
    LL dfn[maxn],low[maxn];
    LL c[maxn],f[maxn],p[maxn],num[maxn];
    struct edge
    {
        LL to;
        LL next;
    }e[maxn*2];
    LL init()
    {
        LL x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    void Clean()
    {
        n=0;topt=0;anst=0,answ=1;sum=0;
        memset(first,0,sizeof(first));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(num,0,sizeof(num));
        memset(c,0,sizeof(c));
        memset(p,0,sizeof(p));
        memset(f,0,sizeof(f));
    }
    void add(LL x,LL y)
    {
        topt++;
        e[topt].to=y;
        e[topt].next=first[x];
        first[x]=topt;
    }
    LL get(LL x)
    {
        if(x&1)return x+1;
        else return x-1;
    }
    void tarjan(LL now,LL from)
    {
        LL s=0;
        dfn[now]=low[now]=++tot;
        for(LL i=first[now];i;i=e[i].next)
        {
            if(get(i)==from)continue;
            LL to=e[i].to;
            if(!dfn[to])
            {
                tarjan(to,i);s++;
                low[now]=min(low[now],low[to]);
                if(low[to]>=dfn[now])c[now]++;
            }
            else
              low[now]=min(low[now],dfn[to]);
        }
        if(from==0)c[now]=s-1;
    }
    LL C(LL m,LL n)
    {
        LL ret=1;
        for(LL i=1;i<=n;i++)
          ret=ret*(m-i+1)/i;
        return ret;
    }
    int dfs(int x)
    {
        if(c[x]>0)
        {
            if(p[x]==1)return 0;
            p[x]=1;return 1;
        }
        int ret=0;
        f[x]=sum;num[sum]++;
        for(int i=first[x];i;i=e[i].next)
        {
            int to=e[i].to;
            if(!f[to])ret+=dfs(to);
        }
        return ret;
    }
    int main()
    {
        freopen("bzoj_2730.in","r",stdin);
        freopen("bzoj_2730.out","w",stdout);
        LL T=0;
        while(1)
        {
            m=init();
            if(m==0)break;
            Clean();
            for(LL i=1;i<=m;i++)
            {
                LL x,y;
                x=init();y=init();
                n=max(n,max(x,y));
                add(x,y);add(y,x);
            }
            for(LL i=1;i<=n;i++)
                if(!dfn[i])tarjan(i,0);
            for(int i=1;i<=n;i++)
            {
                if(c[i]>0)continue;
                if(f[i]==0)
                {
                       memset(p,0,sizeof(p));
                       sum++;
                       int ha=dfs(i);
                       if(ha>=2)continue;
                    if(ha==1)anst++,answ=answ*num[sum];
                    if(ha==0)
                    {
                        anst++;if(num[sum]==1)continue;
                        anst++,answ=answ*C(num[sum],2);
                    }
                }
            }
            cout<<"Case "<<++T<<": "<<anst<<" "<<answ<<endl;
        }
        return 0;
    }
  • 相关阅读:
    jmeter非GUI模式命令
    jmeter性能测试--浪涌测试
    性能测试之场景设计
    性能测试用例实例
    jmeter常见错误及解决方法
    .NET中变量生存期
    SQL数据库从高版本导入低版本
    对称子字符串
    回溯法求解全排列问题(可去除重复排列)
    快速排序及快速选择问题
  • 原文地址:https://www.cnblogs.com/dingmenghao/p/6042424.html
Copyright © 2011-2022 走看看