Mining Your Own Business
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 769 Accepted Submission(s): 97
Problem Description
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.
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.
Input
The
input consists of several test cases. The first line of each case
contains a positive integer N (N <= 5×10^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.
The last test case is followed by a line containing a single zero.
Output
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.
Follow the format of the sample output.
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
Source
referenced from LRJ...
firstly we should figure out Biconnected Component, and then for some component if it has
1.0 cut: this means the given graph is BCC, so we can arbitarily select 2 nodes;
2.1 cut:when this BCC has only one cut, we should select any one node but that cut to build security facilities such that, any node of this component collapses,workers in this component can survive;
3.more cuts:because one BCC can share more cuts with other BCCs, so worker from any one of this component can run to adjacent BCCs to escape, thus in this case, we can simply not build security facilities.
(因为一个双连通分量可以与多个双连通分量相连,形成多个割点,此时该分量任一点collapse,分量内点都可到达相连分量点,从而逃生。)
另外,竟然用到了传说的扩栈(预处理指令?): #pragma comment(linker,"/STACK:102400000,102400000") 而且要用c++编译器交。。。
msdn有关于该预处理指令(?)的解释。
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<vector> #include<cstdlib> #include<algorithm> #include<stack> using namespace std; #define LL __int64 #define ULL unsigned long long #define UINT unsigned int #define MAX_INT 0x7fffffff #define MAX_LL 0x7fffffffffffffff #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) #define MAXN 200100 #pragma comment(linker,"/STACK:102400000,102400000") struct edge{ int u, v; }; int dfn[MAXN], low[MAXN], cnt, tsp; int id[MAXN], iscut[MAXN]; vector<int> bcc[MAXN]; vector<int> g[MAXN]; stack<edge> s; void tarjan(int u, int fa){ int v, child=0; dfn[u]=low[u]=++tsp; for(unsigned int i=0; i<g[u].size(); i++){ v=g[u][i]; edge t; t.u=u; t.v=v; if(!dfn[v]){ child++; s.push(t); tarjan(v, u); low[u]=MIN(low[u], low[v]); if(low[v]>=dfn[u]){ iscut[u]=1; edge k; bcc[++cnt].clear(); while(1){ k=s.top(); s.pop(); if(id[k.u] != cnt) {id[k.u]=cnt; bcc[cnt].push_back(k.u);} if(id[k.v] != cnt) {id[k.v]=cnt; bcc[cnt].push_back(k.v);} if(k.u==u && k.v==v) break; } } } else if(dfn[v]<dfn[u] && v!=fa) s.push(t), low[u]=MIN(low[u], dfn[v]); } if(fa<0 && child==1) iscut[u]=0; } void solve(int n){ tsp=cnt=0; memset(dfn, 0, sizeof(dfn)); memset(id, 0, sizeof(id)); memset(iscut, 0, sizeof(iscut)); tarjan(0, -1); int ans1=0; LL ans2=1; for(int i=1; i<=cnt; i++){ int num=0; for(int j=0; j<bcc[i].size(); j++){ if(iscut[bcc[i][j]]) num++; } if(num==1) ans1++, ans2*=(bcc[i].size()-1); //.............................. } if(cnt==1) ans1=2, ans2=(LL)n*(n-1)/2; //.............................. printf("%d %I64d ", ans1, ans2); } int main(){ freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin); int n, kase=1; while(scanf(" %d", &n)==1 && n){ int i, m=n, u, v; n=-1; for(i=0; i<MAXN; i++) g[i].clear(); for(i=0; i<m; i++){ scanf(" %d %d", &u, &v); u--; v--; g[u].push_back(v); g[v].push_back(u); n=MAX(n,1+v); n=MAX(n, 1+u); } printf("Case %d: ", kase++); solve(n); } return 0; }