bzoj 2730

来源:互联网 发布:淘宝网农村怎么加盟 编辑:程序博客网 时间:2024/06/11 17:23

如果没有割点,任意选两个点建立出口。答案是2 C(n,2);

如果有割点,用搜索去跑,得出所有的连通块,如果一个连通块与超过1个割点相连,就需要建立一个出口,算有多少种情况 就是乘法计算原理。


#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,m;struct node{int to;int next;node(){}node(int a,int b):to(a),next(b){}}edge[1005];int head[1005];int dfn[1005],low[1005],vis[1005],iscut[1005];int root;int tot ,ti;void add_edge(int a,int b){edge[tot] = node(b,head[a]);head[a] = tot++;edge[tot] = node(a,head[b]);head[b] = tot++;}void tarjan(int u,int fa){dfn[u] = ++ti;low[u] = ti;vis[u] = 1;int k = 0;for(int i=head[u];i!=-1;i=edge[i].next){int v = edge[i].to;if(!vis[v]){k++;tarjan(v,u);low[u] = min(low[u],low[v]);}else if(v!=fa){low[u] = min(low[u],dfn[v]);}if(u==root&&k>=2) iscut[u] = 1;if(u!=root&&low[v]>=dfn[u]) iscut[u] = 1;}}int size=0 ,cnt;void dfs(int u,int t){vis[u] = 1;size++;for(int i=head[u];i!=-1;i=edge[i].next){int v = edge[i].to;if(!vis[v]&&!iscut[v])  dfs(v,t);else if(iscut[v]&&vis[v]<t) vis[v] = t,cnt++; }}int main(){int u,v;int t = 1;while(scanf("%d",&m)){if(m==0) break;n = 0;memset(head,-1,sizeof(head));tot = 0;ti = 0;for(int i=0;i<m;i++){scanf("%d%d",&u,&v);add_edge(u,v);n = max(n,u);n = max(n,v);}memset(dfn,0,sizeof(dfn));memset(vis,0,sizeof(vis));memset(low,0,sizeof(low));memset(iscut,0,sizeof(iscut));for(int i=1;i<=n;i++)if(!dfn[i]) root = i,tarjan(i,-1);memset(vis,0,sizeof(vis));int ret = 0;int ans=0;long long cans=1;for(int i=1;i<=n;i++){if(!iscut[i]&&!vis[i]){cnt = 0;size = 0;dfs(i,i);if(cnt<2) ans++,cans*=size;}else if(iscut[i]) ret ++;}printf("Case %d: ",t++);if(ret==0){printf("%d %llu\n",2,n*(n-1)/2);}else{printf("%d %llu\n",ans,cans);}}return 0;}


原创粉丝点击