2730: [HNOI2012]矿场搭建
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2458 Solved: 1147
[Submit][Status][Discuss]
Description
Input
输入文件有若干组数据,每组数据的第一行是一个正整数 N(N≤500),表示工地的隧道数,接下来的 N 行每行是用空格隔开的两个整数 S 和 T,表示挖 S 与挖煤点 T 由隧道直接连接。输入数据以 0 结尾。
Output
输入文件中有多少组数据,输出文件 output.txt 中就有多少行。每行对应一组输入数据的 结果。其中第 i 行以 Case i: 开始(注意大小写,Case 与 i 之间有空格,i 与:之间无空格,: 之后有空格),其后是用空格隔开的两个正整数,第一个正整数表示对于第 i 组输入数据至少需 要设置几个救援出口,第二个正整数表示对于第 i 组输入数据不同最少救援出口的设置方案总 数。输入数据保证答案小于 2^64。输出格式参照以下输入输出样例。
Sample Input
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 2: 4 1
HINT
Source
由于数据范围小,此题可以暴力。。。
显然若非割点坍塌,就无所谓啦,只要考虑坍塌在割点的情况
删去所有割点得到若干连通块,如果图中只有一个连通块,一共只需要设两个
若一个连通块可以到达两个割点的话则不用设置救援出口,否则要设置一个
割点可以删去点然后遍历图求,复杂度n方
对每个割点划分的各个连通块染色,重复染色记为-1
其实可以tarjin求割点,我太懒了
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 inline int read(){ 5 int x=0;int f=1;char ch=getchar(); 6 while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();} 7 while(isdigit(ch)) {x=x*10+ch-‘0‘;ch=getchar();} 8 return x*f; 9 } 10 const int MAXN=1e3+10; 11 struct node{ 12 int y,next; 13 }e[MAXN]; 14 int linkk[MAXN],len,n,m,T,f[MAXN],id[MAXN],vis[MAXN],cnt[MAXN]; 15 inline void insert(int xx,int yy){ 16 e[++len].y=yy;e[len].next=linkk[xx];linkk[xx]=len; 17 } 18 inline void dfs1(int st,int fa){ 19 vis[st]=1; 20 for(int i=linkk[st];i;i=e[i].next){ 21 if(!vis[e[i].y]&&e[i].y!=fa){ 22 dfs1(e[i].y,fa); 23 } 24 } 25 } 26 inline void dfs2(int st,int fa){ 27 if(id[st]==0) id[st]=fa; 28 else id[st]=-1; 29 vis[st]=1; 30 for(int i=linkk[st];i;i=e[i].next){ 31 if(!vis[e[i].y]&&!cnt[e[i].y]){ 32 dfs2(e[i].y,fa); 33 } 34 } 35 } 36 int main(){ 37 //freopen("All.in","r",stdin); 38 //freopen("zh.out","w",stdout); 39 while(1){ 40 m=read(); 41 if(m==0) return 0; 42 T++; 43 printf("Case %d: ",T); 44 memset(linkk,0,sizeof(linkk)); 45 memset(e,0,sizeof(e)); 46 memset(f,0,sizeof(f)); 47 memset(vis,0,sizeof(vis)); 48 memset(id,0,sizeof(id)); 49 memset(cnt,0,sizeof(cnt)); 50 len=0;n=0; 51 for(int i=1;i<=m;i++){ 52 int xx=read();int yy=read(); 53 insert(xx,yy);insert(yy,xx); 54 n=max(max(xx,yy),n); 55 } 56 for(int i=1;i<=n;i++){ 57 memset(vis,0,sizeof(vis)); 58 dfs1((i%n+1),i); 59 for(int j=1;j<=n;j++){ 60 if(!vis[j]&&i!=j) { 61 cnt[i]=1; 62 break; 63 } 64 } 65 } 66 int k=0; 67 memset(vis,0,sizeof(vis)); 68 for(int i=1;i<=n;i++){ 69 if(cnt[i]){ 70 memset(vis,0,sizeof(vis)); 71 for(int j=linkk[i];j;j=e[j].next){ 72 if(!vis[e[j].y]&&!cnt[e[j].y]){ 73 dfs2(e[j].y,++k); 74 } 75 } 76 } 77 } 78 int tot=0;ll ans=1; 79 for(int i=1;i<=n;i++){ 80 if(id[i]!=-1) f[id[i]]++; 81 } 82 for(int i=1;i<=k;i++){ 83 if(f[i]!=0) tot++,ans*=f[i]; 84 } 85 if(!tot) printf("2 %d\n",(n-1)*n/2); 86 else printf("%d %lld\n",tot,ans); 87 } 88 return 0; 89 }