UVALive
来源:互联网 发布:淘宝api 获取订单信息 编辑:程序博客网 时间:2024/06/16 18:23
题意:有m条隧道,这些隧道互相交汇(即没有度为0的情况)。现在要建立逃生竖井,使得某些地方塌陷时员工可以从竖井逃生,求最少要建多少逃生竖井,以及建竖井的方案数。
思路:很容易联想到点联通分量的割点,但当割点塌陷时员工就无法逃脱了。所以不能在割点上建,而要在分量上建。当bcc==1时建连两个(以防其中一个塌陷了),方案数为n(n-1)/2。当bcc不等于1时,考虑在每一个分量上建,如果分量上有2个以及两个以上的割点则不需要建。
#include <iostream>#include <fstream>#include <cstdio>#include <cstring>#include <queue>#include <stack>#include <vector>#include <map>#include <set>#include <cmath>#include <algorithm>#include <functional>#define inf 0x7fffffffusing namespace std;typedef long long ll;const int MAXN=1e5+10;const int MAX=1e5+10;const double eps=1e-6;int n,m,Time,bcc;int low[MAX],dfn[MAX],cut[MAX],belong[MAX];struct EDGE{ int u,v; EDGE(int u,int v):u(u),v(v){}};stack<EDGE>q;vector<int>G[MAX],save[MAX]; //G存图 save存分量void init(){ Time=bcc=1; memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(cut,0,sizeof(cut)); memset(belong,0,sizeof(belong)); for(int i=0;i<=n;i++) G[i].clear(),save[i].clear(); while(q.size()) q.pop(); }void tarjan(int u,int farther){ int child=0,v; dfn[u]=low[u]=Time++; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; EDGE edge(u,v); if(!dfn[v]){ q.push(edge); child++; tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]){ cut[u]=1; save[bcc].clear(); while(1){ edge=q.top(); q.pop(); if(belong[edge.u]!=bcc){ //防止重复 save[bcc].push_back(edge.u); belong[edge.u]=bcc; } if(belong[edge.v]!=bcc){ //防止重复 save[bcc].push_back(edge.v); belong[edge.v]=bcc; } if(edge.u==u&&edge.v==v){ bcc++; break; } } } } else if(dfn[v]<dfn[u]&&v!=farther){ EDGE edge(u,v); q.push(edge); low[u]=min(low[u],dfn[v]); } } if(farther<0&&child==1){ //根节点特判 cut[u]=0; }}void get_bcc(){ for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,-1);}int main(){ #ifdef ONLINE_JUDGE #else freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif int flag=1; while(cin>>m){ if(m==0) break; n=m*2; init(); int u,v; for(int i=1;i<=m;i++){ scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); n=max(n,max(u,v)); } get_bcc(); int ansa=0; ll ansb=0; if(bcc-1==1){ ansa=2; ansb=(ll)save[1].size()*(save[1].size()-1)/2; } else{ ansb=1; for(int i=1;i<bcc;i++){ int cnt=0; for(int j=0;j<save[i].size();j++){ if(cut[save[i][j]]) cnt++; } if(cnt==1){ ansa++; ansb=ansb*(save[i].size()-1); //cout<<save[i].size()-1<<endl; } } } printf("Case %d: %d %lld\n",flag++,ansa,ansb ); } return 0; }
阅读全文
0 0
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- [状压DP] HDU 5823 Color II
- LightOJ
- oracle数据库emp表 及其关联的表
- myeclipse 搭建最简单的Rest 服务
- 线段树模板
- UVALive
- 深拷贝和浅拷贝
- 割点
- socket 多线程http服务器
- ACdream 1073 雷霆战机 (模拟 + set容器的使用)
- AngularJs+用户信息表基本功能实现
- C++中vector容器的基本用法总结
- jsp模拟留言板
- C++PRIMER第十一章练习