题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19845
【思路】
点-双连通分量。
求出bcc,对于每个bcc而言,最优的方案就是在每一个只有一个割点的bcc中安置一个逃生装置。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<stack> 4 #include<vector> 5 #include<iostream> 6 #include<cstdlib> 7 #define FOR(a,b,c) for(int a=(b);a<(c);a++) 8 using namespace std; 9 10 typedef long long LL; 11 const int maxn = 100000+10; 12 13 struct Edge{ int u,v; 14 }; 15 16 int pre[maxn],iscut[maxn],bccno[maxn],dfs_clock,bcc_cnt; 17 vector<int> G[maxn],bcc[maxn]; 18 19 stack<Edge> S; 20 21 int dfs(int u,int fa) { 22 int lowu=pre[u]=++dfs_clock; 23 int ch=0; 24 for(int i=0;i<G[u].size();i++) { 25 int v=G[u][i]; 26 Edge e=(Edge) {u,v}; 27 if(!pre[v]) { 28 S.push(e); 29 ch++; 30 int lowv=dfs(v,u); 31 lowu=min(lowu,lowv); 32 if(lowv>=pre[u]) { 33 iscut[u]=1; 34 bcc_cnt++; bcc[bcc_cnt].clear(); 35 for(;;) { 36 Edge x=S.top(); S.pop(); 37 if(bccno[x.u]!=bcc_cnt) bcc[bcc_cnt].push_back(x.u),bccno[x.u]=bcc_cnt; 38 if(bccno[x.v]!=bcc_cnt) bcc[bcc_cnt].push_back(x.v),bccno[x.v]=bcc_cnt; 39 if(x.u==u && x.v==v) break; 40 } 41 } 42 } 43 else if(pre[v]<pre[u] && v!=fa) { 44 S.push(e); lowu=min(lowu,pre[v]); 45 } 46 } 47 if(fa<0 && ch==1) iscut[u]=0; 48 return lowu; 49 } 50 void find_bcc(int n) { 51 memset(pre,0,sizeof(pre)); 52 memset(iscut,0,sizeof(iscut)); 53 memset(bccno,0,sizeof(bccno)); 54 dfs_clock=bcc_cnt=0; 55 for(int i=0;i<n;i++) 56 if(!pre[i]) dfs(i,-1); 57 } 58 59 int n,m,kase; 60 61 int main() { 62 while(scanf("%d",&m) && m) { 63 int u,v; 64 n=0; 65 for(int i=0;i<2*m;i++) G[i].clear(); 66 for(int i=0;i<m;i++) { 67 scanf("%d%d",&u,&v); 68 u--,v--; 69 n=max(n,max(u,v)); 70 G[u].push_back(v); 71 G[v].push_back(u); 72 } 73 while(!S.empty()) S.pop(); 74 75 find_bcc(n); 76 77 LL ans1=0,ans2=1; 78 for(int i=1;i<=bcc_cnt;i++) { 79 int cnt=0; 80 for(int j=0;j<bcc[i].size();j++) 81 if(iscut[bcc[i][j]]) cnt++; 82 if(cnt==1) { 83 ans1++; ans2*=(long long)(bcc[i].size()-1); 84 } 85 } 86 if(bcc_cnt==1) { 87 ans1=2; ans2=bcc[1].size()*(bcc[1].size()-1)/2; 88 } 89 printf("Case %d: %lld %lld\n",++kase,ans1,ans2); 90 } 91 return 0; 92 }
时间: 2024-10-13 17:48:04