標籤:技術 cas tarjan 指南 ges ack mini sed blog
【演算法】點雙連通分量
【題解】詳見《演算法競賽入門競賽入門經典訓練指南》P318-319
細節在代碼中用important標註。
#include<cstdio>#include<algorithm>#include<vector>#include<stack>#include<cstring>using namespace std;const int maxm=50010;struct edge{int u,v,from;}e[maxm*3];int first[maxm],iscut[maxm],dfn[maxm],low[maxm],bccno[maxm],bcc_cnt,dfsnum,tot,n,m,kase;vector<int>bcc[maxm];stack<int>s;void insert(int u,int v){tot++;e[tot].u=u;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}void tarjan(int x,int fa){ dfn[x]=low[x]=++dfsnum; int child=0; for(int i=first[x];i;i=e[i].from) if(e[i].v!=fa) { int y=e[i].v;// s.push(i); if(!dfn[y]) { s.push(i);// child++; //important tarjan(y,x); low[x]=min(low[x],low[y]); if(low[y]>=dfn[x]) { iscut[x]=1; bcc_cnt++; bcc[bcc_cnt].clear(); for(;;) { int now=s.top();s.pop(); int u=e[now].u,v=e[now].v; if(bccno[u]!=bcc_cnt){bcc[bcc_cnt].push_back(u);bccno[u]=bcc_cnt;} if(bccno[v]!=bcc_cnt){bcc[bcc_cnt].push_back(v);bccno[v]=bcc_cnt;}// printf("%d\n",bcc_cnt); if(u==x&&v==y)break; } } } else if(dfn[y]<dfn[x])s.push(i),low[x]=min(low[x],dfn[y]);//important } if(fa<0&&child==1)iscut[x]=0;}int main(){ scanf("%d",&m); while(m!=0) { memset(first,0,sizeof(first)); n=0;tot=0;bcc_cnt=0; for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); n=max(n,max(u,v)); insert(u,v); insert(v,u); } memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(iscut,0,sizeof(iscut)); memset(bccno,0,sizeof(bccno)); dfsnum=0; while(!s.empty())s.pop(); for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,-1); long long ans1=0,ans2=1; for(int i=1;i<=bcc_cnt;i++) { int cut_cnt=0; for(int j=0;j<bcc[i].size();j++) if(iscut[bcc[i][j]])cut_cnt++; if(cut_cnt==1) { ans1++; ans2*=(long long)(bcc[i].size()-cut_cnt); } } if(bcc_cnt==1) { ans1=2; ans2=bcc[1].size()*(bcc[1].size()-1)/2; } printf("Case %d: %lld %lld\n",++kase,ans1,ans2); scanf("%d",&m); } return 0;}
View Code
【LA】5135 Mining Your Own Business