BZOJ2730 [HNOI2012]矿场搭建
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:BZOJ2730
正解:求割点+搜索
解题报告:
考虑一个点如果可以在不经过别的割点的情况下,走到两个或者以上的割点时,那么无需放。
暴力求一遍割点,给每个点染个色,统计一下答案即可。
//It is made by ljh2000 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <string> #include <complex> using namespace std; typedef long long LL; typedef long double LB; typedef complex<double> C; const double pi = acos(-1); const int MAXN = 520; const int MAXM = 1024; int n,m,ecnt,first[MAXN],to[MAXM],next[MAXM],Tim,bel[MAXN],tot,ans,cnt[MAXN]; int cut[MAXN],vis[MAXN]; LL ans2; inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; } inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } inline void dfs(int x,int fa){ vis[x]=Tim; for(int i=first[x];i;i=next[i]) { int v=to[i]; if(vis[v]==Tim || v==fa) continue; dfs(v,fa); } } inline void dfs2(int x){ vis[x]=1; if(bel[x]==0) bel[x]=Tim; else bel[x]=-1; for(int i=first[x];i;i=next[i]) { int v=to[i]; if(vis[v] || cut[v]) continue; dfs2(v); } } inline void work(){ int x,y; int Case=0; while(1) { m=getint(); if(m==0) break; memset(bel,0,sizeof(bel)); Case++; printf("Case %d: ",Case); memset(cut,0,sizeof(cut)); memset(vis,0,sizeof(vis)); n=tot=ans=ecnt=0; ans2=1; memset(first,0,sizeof(first)); for(int i=1;i<=m;i++) { x=getint(); y=getint(); n=max(n,x); n=max(n,y); link(x,y); link(y,x); } for(int i=1;i<=n;i++) { Tim++; for(int j=first[i];j;j=next[j]) { dfs(to[j],i); break; } cut[i]=0; for(int j=1;j<=n;j++) if(j!=i && vis[j]!=Tim) { cut[i]=1; break; } } Tim=0; for(int i=1;i<=n;i++) if(cut[i]) { memset(vis,0,sizeof(vis)); for(int j=first[i];j;j=next[j]) if(!cut[to[j]] && !vis[to[j]]) { Tim++; dfs2(to[j]); } } memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++) if(bel[i]!=-1) cnt[bel[i]]++; for(int i=1;i<=n;i++) if(cnt[i]>0) ans++,ans2*=cnt[i]; if(ans==0) printf("2 %d\n",n*(n-1)>>1); else printf("%d %lld\n",ans,ans2); } } int main() { work(); return 0; }
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!