书P401
需要具备的知识:
①:tarjan求割点与割边:https://blog.nowcoder.net/n/dc5fbd4588164fb4b37847a11ea7f499
若一张无向图不存在割点,则为点双连通图。
若一张无向图不存在割边(桥),则为边双连通图。
无向图的极大点双连通子图为点双连通分量,简称“v-DCC”。
无向图的极大边双连通子图为边双连通分量,简称“e-DCC”。
二者统称为双连通分量,简称“DCC”。
1、边双连通分量
模版:https://www.luogu.com.cn/problem/T103489
#include <bits/stdc++.h>
using namespace std;
const int SIZE=3e5+1;
int head[SIZE],ver[SIZE*2],Next[SIZE*2];
int dfn[SIZE],low[SIZE];
bool bridge[SIZE*2];
int n,m,tot,num;
int c[SIZE],dcc;
void dfs(int x)
{
c[x]=dcc;
for(int i=head[x];i;i=Next[i])
{
int y=ver[i];
if(c[y]||bridge[i]) continue;
dfs(y);
}
}
void add(int x,int y)
{
ver[++tot]=y,Next[tot]=head[x],head[x]=tot;
}
void tarjan(int x,int in_edge)
{
dfn[x]=low[x]=++num;
for(int i=head[x];i;i=Next[i])
{
int y=ver[i];
if(!dfn[y])
{
tarjan(y,i);
low[x]=min(low[x],low[y]);
if(low[y]>dfn[x])
{
bridge[i]=bridge[i^1]=true;
}
}
else if(i!=(in_edge^1))
low[x]=min(low[x],low[y]);
}
}
int main()
{
cin>>n>>m;
tot=1;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i]) tarjan(i,0);
}
for(int i=1;i<=n;i++)
{
if(!c[i])
{
++dcc;
dfs(i);
}
}
cout<<dcc<<endl;
//cout<<"There are "<<dcc<<" e-DCCs."<<endl;
/*for(int i=1;i<=n;i++)
{
cout<<i<<" belongs to DCC "<<c[i]<<"."<<endl;
}*/
return 0;
}2、
3、点双连通分量
模版题:https://www.luogu.com.cn/problem/P3225
#include <bits/stdc++.h>
using namespace std;
const int SIZE=100010;
int head[SIZE],ver[SIZE*2],Next[SIZE*2];
int dfn[SIZE],low[SIZE],Stack[SIZE];
bool cut[SIZE*2];
vector<vector<int> > dcc;
int n,m,tot,num,root,top,cnt;
void add(int x,int y)
{
ver[++tot]=y,Next[tot]=head[x],head[x]=tot;
}
void tarjan(int x)
{
dfn[x]=low[x]=++num;
Stack[++top]=x;
if(x==root&&head[x]==0)
{
dcc[++cnt].push_back(x);
return;
}
int flag=0;
for(int i=head[x];i;i=Next[i])
{
int y=ver[i];
if(!dfn[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x])
{
flag++;
if(x!=root||flag>1) cut[x]=true;
cnt++;
int z;
while(z!=y)
{
z=Stack[top--];
dcc[cnt].push_back(z);
}
dcc[cnt].push_back(x);
}
}
else low[x]=min(low[x],dfn[y]);
}
}
int main()
{
cin>>n>>m;
tot=1;
for(int i=0;i<=n;i++)
{
dcc.push_back({});
}
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
if(x==y) continue;
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
root=i;
tarjan(i);
}
}
for(int i=1;i<=cnt;i++)
{
cout<<"v-DCC "<<i<<":";
for(int j=0;j<dcc[i].size();j++)
{
cout<<" "<<dcc[i][j];
}
cout<<endl;
}
return 0;
}
京公网安备 11010502036488号