算法
无向连通图点双连通分支是指不包含割点的极大连通子图
割点可以属于多个点双连通分支,其余点和每条边只属于且属于一个点双连通分支。
无重边的无向连通图点双连通分支
//无重边的无向连通图点双连通分支
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
const int N=200;
vector<int>g[N];
int dfn[N],low[N];
int index,n,m;//index编号 n点数 m边数
struct Edge{
int u,v;
Edge(int u,int v):u(u),v(v){}
};
stack<Edge>s;
int t;
void Tarjan(int u,int father)//father是u的父节点
{
dfn[u]=low[u]=index++;
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
if(!dfn[v]){//v没有被访问
//树边入栈
s.push(Edge(u,v));
Tarjan(v,u);
low[u]=min(low[u],low[v]);
Edge temp(0,0);
if(dfn[u]<=low[v]){
/*从一条边往下走,走完后发现自己是割点,则栈中的边一定全是和自己在一个双
连通分量里面,根节点总是和其下的某些点在同一个双连通分量里面
*/ cout<<"Block No:"<<++t<<endl;
do{
temp=s.top();
s.pop();
cout<<temp.u<<","<<temp.v<<endl;
}while(!(temp.u==u&&temp.v==v));
}
}
else if(father!=v){//连到父节点的回边不考虑
low[u]=min(low[u],dfn[v]);
//连接到祖先的回边要入栈,但是连接到儿子的边,此处肯定已经入过栈了
if(dfn[u]>dfn[v])
s.push(Edge(u,v));
}
}
}
int main()
{
int u,v;
index=1;
cin>>n>>m;//点数 边数
for(int i=1;i<=m;i++){
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
Tarjan(1,0);
return 0;
}