点双联通分量模板

xiaoxiao2021-02-28  80

#include <bits/stdc++.h> #define MAXN 10005 using namespace std; struct Tarjan { struct edge { int u,v; edge(int uu=0,int vv=0):u(uu),v(vv){} bool operator ==(const edge &p)const { return (u==p.u&&v==p.v)||(v==p.u&&u==p.v); } }; int n; //点的个数 vector<int> e[MAXN]; //图 int DFN[MAXN],LOW[MAXN]; int index; //编号计数器 edge stk[MAXN]; //栈 int top; vector<vector<edge> > Ans; //记录答案 bool iscut[MAXN]; //记录点是否为割点 void init(int N) //初始化 { n=N; Ans.clear(); for(int i=1;i<=n;i++) e[i].clear(); top=0; index=0; memset(DFN,-1,sizeof(DFN)); memset(iscut,0,sizeof(iscut)); } void AddEdge(int u,int v) //添加边 { e[u].push_back(v); e[v].push_back(u); } void DFS(int u,int prt) //从点u开始搜索 { DFN[u]=LOW[u]=++index; int child=0; for(int i=0;i<e[u].size();i++) { int &v=e[u][i]; if(v==prt)continue; if(DFN[v]!=-1&&DFN[v]>=DFN[u])continue; stk[top++]=edge(u,v); if(DFN[v]==-1) { child++; DFS(v,u); LOW[u]=min(LOW[u],LOW[v]); if(LOW[v]>=DFN[u]) { iscut[u]=true; vector<edge> ans; while(!(stk[top-1]==edge(u,v))) { ans.push_back(stk[top-1]); top--; } ans.push_back(stk[top-1]); top--; Ans.push_back(ans); } } else LOW[u]=min(LOW[u],DFN[v]); } if(prt==-1&&child==1)iscut[u]=false; } void Solve() { for(int i=1;i<=n;i++) if(DFN[i]==-1)DFS(i,-1); } }T; int main() { int n; while(scanf("%d",&n)==1) { T.init(n); int m; scanf("%d",&m); for(int i=0;i<m;i++) { int u,v; scanf("%d%d",&u,&v); T.AddEdge(u,v); } T.Solve(); for(int i=0;i<T.Ans.size();i++) { for(int j=0;j<T.Ans[i].size();j++) printf("(%d,%d) ",T.Ans[i][j].u,T.Ans[i][j].v); printf("\n"); } } }
转载请注明原文地址: https://www.6miu.com/read-85313.html

最新回复(0)