zoukankan      html  css  js  c++  java
  • 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)。

    分类标签 Tags 点此展开 

    题意:
    *给定一个n个点,m条边的图。要在这n个点选择若干点建造避难所,使得无论哪个点爆炸,每个点上的人都能逃到这个避难所去。
    *求最少避难所个数,以及在这个前提下的方案总数。
    解析:
    *求出所有割点后。对于剩下的所有联通块都缩成一个点。
    *接下来对于所有点,若该点与两个点相连,则不需要建立避难所,若只与一个点相连,则需要建立1个避难所,若没有相连,则需要建立2个避难所。
    *方案总数用乘法原理乘起来就可以了。
     AC代码:
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #define ll long long
    using namespace std;
    inline const int read(){
        register int x=0,f=1;
        register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return x*f;
    }
    const int N=510;
    vector<int>grap[N];
    int n,m,cas,pd,dfn[N],low[N],son,ans,sum;
    int siz[N],r[N],matc[N];
    bool f[N],cut[N],mark[N];
    ll cnt;
    void Cl(){
        cnt=1;pd=0;sum=0;n=0;son=0;ans=0;
        memset(f,0,sizeof f);
        memset(r,0,sizeof r);
        memset(dfn,0,sizeof dfn);
        memset(low,0,sizeof low);
        memset(cut,0,sizeof cut);
        memset(siz,0,sizeof siz);
        memset(mark,0,sizeof mark);
        memset(grap,0,sizeof grap);
        memset(matc,0,sizeof matc);
    }
    void tarjan(int v,int root){
        dfn[v]=low[v]=++pd;
        mark[v]=1;
        for(int i=0;i<grap[v].size();i++){
            int w=grap[v][i];
            if(!dfn[w]){
                tarjan(w,root);
                low[v]=min(low[v],low[w]);
                if(low[w]>=dfn[v]&&v!=root) cut[v]=1;
                else if(v==root) son++;
            }
            else if(mark[w]){
                low[v]=min(low[v],dfn[w]);
            }
        }
    }
    void dfs(int x){
        f[x]=1;siz[sum]++;
        for(int i=0;i<grap[x].size();i++){
            int v=grap[x][i];
            if(f[v]) continue;
            if(!cut[v]) dfs(v);
            else if(matc[v]!=sum){
                matc[v]=sum;r[sum]++;
            }
        }
    }
    int main(){
        for(m=read();m;m=read()){
            Cl();
            for(int x,y,i=1;i<=m;i++){
                scanf("%d%d",&x,&y);
                n=max(n,x);
                n=max(n,y);
                grap[x].push_back(y);
                grap[y].push_back(x);
            }
            for(int i=1;i<=n;i++) if(!dfn[i]){
                son=0;
                tarjan(i,i);
                if(son>1) cut[i]=1;
            }
            for(int i=1;i<=n;i++) if(!cut[i]&&!f[i]){
                sum++;dfs(i);
            }
            if(sum==1){
                ans=2;
                cnt=(ll)n*(n-1)/2;
            }
            else{
                for(int i=1;i<=sum;i++){
                    if(r[i]==1){
                        ans++;
                        cnt*=(ll)siz[i];
                    }
                }
            }
            printf("Case %d: %d %lld
    ",++cas,ans,cnt);
        }
        return 0;
    }
     
  • 相关阅读:
    verilog 基础知识
    excel函数提取身份证出生日期,分离日期时间的日期和时间
    excel函数提取内容中的汉字
    excel匹配函数vlookup和lookup
    excel计数函数COUNTIF、COUNTIFS
    excel函数sum、sumif和sumifs
    excel替换函数substitute
    excel判断数据是否存在另一列中
    python用random模块模拟抽奖逻辑(print修改end参数使打印结果不分行)
    excel用函数去掉单元格内容中的括号,并只保留单元格里面的内容
  • 原文地址:https://www.cnblogs.com/shenben/p/6044709.html
Copyright © 2011-2022 走看看