记录编号 343579 评测结果 AAAAAAAAAA
题目名称 [HNOI 2012] 矿场搭建 最终得分 100
用户昵称 Gravatar可以的. 是否通过 通过
代码语言 C++ 运行时间 0.041 s
提交时间 2016-11-09 15:17:23 内存使用 0.25 MiB
显示代码纯文本
#include <iostream>
#include <stdio.h>
#include <cstring>
#define Mem(a,v) memset(a,v,sizeof a)
#include <algorithm>
using namespace std;
/******************************************\
freopen(".in","r",stdin);
	freopen(".out","w",stdout);
\******************************************/
void qkin(int &res){
	int x,f=1; char ch;
	while(ch=getchar(),ch<'0'||ch>'9')if(ch=='-')f=-1;
	x=ch-48;
	while(ch=getchar(),ch>='0'&&ch<='9')x=x*10+ch-48;
	res = x * f;
}
void read(int &a){ qkin(a); }
void read(int &a,int &b){ qkin(a); qkin(b); }
void read(int &a,int &b,int &c){ qkin(a); qkin(b); qkin(c); }
typedef long long LL;
#define maxn 1010
int Case = 0;
int T,m;//最大点   边数 
LL ans1,ans2;
int len,head[maxn];//head[]=-1 
bool Wall[maxn],iscut[maxn];//记录割点
int block_cnt = 0 , cut_cnt = 0;
int dfn[maxn],ti,Low[maxn],col[maxn],Color,fa[maxn],du[maxn];
struct Edge
{
	int to,next;
}e[maxn];
bool vis[maxn];//标记被访问的边和反边 
void Add_Edge(int x,int y){
	//注意len从0起 
	e[len].to = y; e[len].next = head[x]; head[x] = len++;
}
int Point_sum[maxn]; 
bool Point_vis[maxn],cut_vis[maxn];
void Dfs(int x){
	Low[x] = dfn[x] = ++ ti;
	col[x] = -Color;
	Point_sum[Color] ++ ;
	for(int i = head[x] ; i != -1 ; i = e[i].next){
		if(!vis[i]){
			vis[i] = 1;
			vis[i^1] = 1;
			int p = e[i].to;
			if(!col[p]){
				du[x] ++ ;
				fa[p] = x;
				Dfs(p);
				Low[x] = min(Low[p],Low[x]);
			}
			else if(col[p] < 0){
				Low[x] = min(Low[x],dfn[p]);	
			}	
		}	
	}
	col[x] = Color;
}
void Dfs2(int x){
	Point_vis[x] = 1;
	block_cnt ++ ;
	for(int i = head[x] ; i != -1 ; i = e[i].next){
		int p = e[i].to;
		if(!Point_vis[p]){
			if(iscut[p]){
				if(!cut_vis[p]) cut_cnt ++ ; 
				cut_vis[p] = 1;
			}
			else Dfs2(p);	
		}	
	}	
}
void Work(){
	/*  建边  */
	len = 0;
	Mem(head,-1); 
	Mem(Wall,0);
	T = 0;
	Mem(Point_sum,0);
	for(int i = 1 ; i <= m ; i ++ ){
		int x,y; 
		read(x,y);
		T = max(T,max(x,y));
		Wall[x] = Wall[y] = 1;
		Add_Edge(x,y);
		Add_Edge(y,x);	
	}	
	/*  DFS 求割点  */
	ti = 0;
	Color = 0;
	Mem(dfn,0);
	Mem(col,0);
	Mem(Low,0);
	Mem(vis,0);
	Mem(fa,0);
	Mem(du,0);
	for(int i = 1 ; i <= T ; i ++ ){
		if(!Wall[i]) continue;
		if(!col[i]){
			fa[i] = 0;
			Color ++ ;
			Dfs(i);	
		}	
	}
	Mem(iscut,0);
	for(int i = 1 ; i <= T ; i ++ ){
		if(!Wall[i]) continue;
		if(!fa[i] && du[i] >= 2){
			iscut[i] = 1;	
		}
		if(fa[i]){
			if(fa[fa[i]]!=0 && Low[i] >= dfn[fa[i]]){
				iscut[fa[i]] = 1;	
			}	
		}
	}
	int cut_sum = 0;
	for(int i = 1 ; i <= T ; i ++ ){
		if(iscut[i]) cut_sum ++;	
	}
	ans1 = 0;
	ans2 = 1;
	if(cut_sum == 0){
		//整张图强连通
		for(int i = 1 ; i <= Color ; i ++ ){
			ans1 += 2;
			ans2 *= (LL)((LL)(Point_sum[i]-1)*(LL)Point_sum[i]/2);	
		}
		return;	
	}
	/*  对非割点 DFS  */
	Mem(Point_vis,0);
	ans1 = 0;
	ans2 = 1;
	for(int i = 1 ; i <= T ; i ++ ){
		if(!Wall[i]) continue;
		if(!iscut[i] && !Point_vis[i]){
			block_cnt = 0;
			cut_cnt = 0;
			Mem(cut_vis,0);
			Dfs2(i);
			if(cut_cnt == 1){
				ans1 ++ ;
				ans2 *= (LL)(block_cnt);	
			}
		}
	}
}
int main(){
	freopen("bzoj_2730.in","r",stdin);
	freopen("bzoj_2730.out","w",stdout);
	while(scanf("%d",&m) == 1){
		if(!m) break;
		Work();	
		printf("Case %d: ",++Case);
		printf("%lld %lld\n",ans1,ans2);
	}
	getchar(); getchar();
	fclose(stdin); fclose(stdout);
	return 0;
}
/*
6
1 2
1 3
2 3
2 4
2 5
4 5
4
1 2
1 3
2 4 
4 3
5
1 2
2 4
2 3
3 4
4 5
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
4
1 2
1 3
1 4
3 5
0

2
1 2
3 4

4
1 2
2 3
1 3
4 5
*/