首页 > 代码库 > 无向图双连通分量 模板
无向图双连通分量 模板
//点-双连通分量模板。 #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; }
无向图双连通分量 模板
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。