• BUSINESS


    题目描述

    John Digger is the owner of a large illudium phosdex mine. The mine is made up of a series of tunnels that meet at various large junctions. Unlike some owners, Digger actually cares about the welfare of his workers and has a concern about the layout of the mine. Specifically, he worries that there may a junction which, in case of collapse, will cut off workers in one section of the mine from other workers (illudium phosdex, as you know, is highly unstable). To counter this, he wants to install special escape shafts from the junctions to the surface. He could install one escape shaft at each junction, but Digger doesn't care about his workers that much. Instead, he wants to install the minimum number of escape shafts so that if any of the junctions collapses, all the workers who survive the junction collapse will have a path to the surface.

    Write a program to calculate the minimum number of escape shafts and the total number of ways in which this minimum number of escape shafts can be installed.

    输入格式

    The input consists of several test cases. The first line of each case contains a positive integer N (N5 ^{ . } 10 4 ^{4} 4 ) indicating the number of mine tunnels. Following this are N lines each containing two distinct integers s and t, where s and t are junction numbers. Junctions are numbered consecutively starting at 1. Each pair of junctions is joined by at most a single tunnel. Each set of mine tunnels forms one connected unit (that is, you can get from any one junction to any other).

    The last test case is followed by a line containing a single zero.

    输出格式

    For each test case, display its case number followed by the minimum number of escape shafts needed for the system of mine tunnels and the total number of ways these escape shafts can be installed. You may assume that the result fits in a signed 64-bit integer.

    Follow the format of the sample output.

    题意翻译

    有一座底下的稀有金属矿由n条隧道和一些连接点组成,其中每条隧道连接两个连接点。任意两个连接点之间最多只有一条隧道。为了降低矿工的危险,你的任务是在一些连接点处安装太平井,使得无论哪个连接点倒塌,不在此连接点的所有矿工都能到达太平井逃生(假定除了倒塌的连接点外,其他的连接点和隧道完好无损)。为了节约成本,你应当在尽量少的连接点安装太平井,还需要计算当太平井的数目最少时的安装方案总数。 【输入格式】 输入包含多组数据,第一行为隧道的条数n(n <= 50 000),以下为n行,每行两个整数,即一条隧道两端的连接点编号(所有连接点从1开始标号)。每组数据的所有连接点保证联通。 【输出格式】 对于每组数据,输出两个整数,即最少需要安装的太平井的数目以及对应的方案总数。方案总数保证在64位带符号整数的范围内。
    输入输出样例

    输入 #1

    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

    输出 #1

    Case 1: 2 4

    Case 2: 4 1

    注意:

    • 题目中说了可能图并不连通,所以我们可能要求很多次Tarjan函数,但是不要忘记每次从主函数进入的时候,一定把栈清空,即top=0
      然后最后就是分着求每一个点双对结果的贡献。
    • 该点双有0个割点则最少应有2个逃生点,方案数(size*(size-1))
    • 该点双有1个割点则最少应有1个逃生点,方案数(size-1)
    • 该点双有2个及以上割点则最少有0个逃生点,该点双也就无方案数。
    • 最后将逃生点数相加即总逃生点数,根据分步乘法原理将各点双方案数相乘,对于没有方案的就不乘(而且初始时是1)。

    Code

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int maxn=5e4+5,maxm=1e5+5;
    struct Edge{
    	int next,to;
    }e[maxm];
    int n,m,rt,Time,head[maxn],low[maxn],dfn[maxn],sta[maxn],top,dcnt,cc;
    bool cut[maxn];
    vector<int> dcc[maxn];
    inline long long rd(){
        register int x=0,f=0;register char ch=getchar();
        while(ch<'0'||ch>'9')f|=ch=='-',ch=getchar();
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
        return f?-x:x;
    }
    void A(int x,int y){
    	e[++head[0]].to=y;
    	e[head[0]].next=head[x];
    	head[x]=head[0];
    }
    void T(int u){
    	low[u]=dfn[u]=++Time;
    	sta[++top]=u;
    	int cd=0;
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(!dfn[v]){
    			T(v);
    			low[u]=min(low[u],low[v]);
    			if(low[v]>=dfn[u]){
    				++cd;
    				if(u!=rt||cd>1)cut[u]=1;
    				dcnt++;
    				int x;
    				do{
    					x=sta[top--];
    					dcc[dcnt].push_back(x);
    				}while(x!=v);
    				dcc[dcnt].push_back(u);
    			}
    		}
    		else low[u]=min(low[u],dfn[v]);
    	}
    }
    void Init(){
    	memset(dfn,0,sizeof dfn);
    	memset(low,0,sizeof low);
    	for(int i=1;i<=dcnt;++i)dcc[i].clear();
    	memset(cut,0,sizeof cut);
    	memset(head,0,sizeof head);
    	memset(sta,0,sizeof sta);
    	Time=0;dcnt=0;
    }
    int main(){
    	int Case=0;
    	while(scanf("%d",&m)!=EOF&&m){
    		Init();
    		for(int i=1,x,y;i<=m;++i){
    			x=rd();y=rd();
    			n=max(n,max(x,y));
    			if(x==y)continue;
    			A(x,y);A(y,x);
    		}
    		for(int i=1;i<=n;++i)if(!dfn[i])top=0,rt=i,T(i);
    		ll ans=0,ccc=1;
    		if(dcnt==1) printf("Case %d: 2 %lld
    ",++Case,(ll)dcc[1].size()*(dcc[1].size()-1)/2);
    		else{
    			for(int i=1;i<=dcnt;++i){
    				int cc=0;ll sz=(ll)dcc[i].size();
    				for(int j=0;j<sz;++j) if(cut[dcc[i][j]])cc++;
    				if(cc==0)ans+=2,ccc*=(sz*(sz-1))/2;
    				else if(cc==1)ans++,ccc*=(sz-1);
    			}
    			printf("Case %d: %lld %lld
    ",++Case,ans,ccc);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Django框架基础之序列化
    资产采集
    CMDB
    数据库--三层架构
    Django 项目一补充
    评论楼
    图片预览
    验证码
    如何使用C/C++动态库与静态库中的宏
    Matlab 直线方程、采样函数
  • 原文地址:https://www.cnblogs.com/Lour688/p/13209972.html
Copyright © 2020-2023  润新知