标签:iostream lock 记录 ons namespace logs name 模板 结束
//点-双连通分量模板。 #include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<stack> using namespace std; struct Edge { int u,v; };//u,v是边的两个端点 const int maxn=100005; int n,m; int pre[maxn],iscut[maxn],bccno[maxn],dfs_clock,bcc_cnt; //pre[i]记录i点的编号,iscut[i]标记i点是不是割点,bccno[i]记录i点所属的双连通分量 //bcc_cnt,双联通分量计数器 vector<int>G[maxn],bcc[maxn];//G存原图,bcc[i]存第i个连通分量中的点 stack<Edge>s; int dfs(int u,int fa)//u和u的父亲 { int lowu=pre[u]=++dfs_clock; int child=0; for(int i=0;i<(int)G[u].size();i++){ int v=G[u][i]; Edge e=(Edge){u,v}; if(!pre[v]){//没有访问过v s.push(e); child++; int lowv=dfs(v,u); lowu=min(lowu,lowv);//用后代的low函数更新自己 if(lowv>=pre[u]){ iscut[u]=true; bcc_cnt++; //bcc从1开始编号 bcc[bcc_cnt].clear(); for(;;){ Edge x=s.top(); s.pop(); if(bccno[x.u]!=bcc_cnt) {bcc[bcc_cnt].push_back(x.u);bccno[x.u]=bcc_cnt;} if(bccno[x.v]!=bcc_cnt) {bcc[bcc_cnt].push_back(x.v);bccno[x.v]=bcc_cnt;} if(x.u==u&&x.v==v) break; } } } else if(pre[v]<pre[u]&&v!=fa){ s.push(e); lowu=min(lowu,pre[v]);//用反向边更新自己 } } if(fa<0&&child==1) iscut[u]=0; return lowu; } void find_bcc() { //调用结束后s保证为空,所以不用清空 memset(pre,0,sizeof(pre)); memset(iscut,0,sizeof(iscut)); memset(bccno,0,sizeof(bccno)); dfs_clock=bcc_cnt=0; for(int i=0;i<n;i++) if(!pre[i]) dfs(i,-1); } int main() { /* int a,b; cin>>n>>m; for(int i=0;i<m;i++){ cin>>a>>b; G[a].push_back(b); G[b].push_back(a); } find_bcc(); for(int i=0;i<n;i++){ cout<<bccno[i]<<endl; } for(int i=1;i<=bcc_cnt;i++){ for(int j=0;j<(int)bcc[i].size();j++){ cout<<bcc[i][j]<<" "; } cout<<endl; } for(int i=0;i<n;i++) cout<<iscut[i]<<endl; */ return 0; }
标签:iostream lock 记录 ons namespace logs name 模板 结束
原文地址:http://www.cnblogs.com/--ZHIYUAN/p/6351619.html