兔已经讲的非常好了,我就讲我的理解吧!!!
大多数情况下,图论是比树结构要复杂多的,所以引入了一个圆方树的一种数据结构。
把无向图转化为由原点与点双连通分量组成的树,原图的每一个点都是一个圆点,每一个点双都是一个方点,所以形成的新图有 \(n+c\) 个点,每个点双转为方点时形成一个菊花图。
我直接上代码!!
-
要从新图上建边建点。
-
cnt 要初始化为 n。
-
注意退栈操作,最后记住把top退出。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=400005;
#define ll long long
int n;
int s,t;
vector<int> v[N],a[N];
int low[N],dfn[N],top=0,st[N],cnt,tot;
void tarjan(int x){
low[x]=dfn[x]=++tot;
st[++top]=x;
for(int y:v[x]){
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]==dfn[x]){
++cnt;
for(int b=0;b!=y;--top){
b=st[top];
a[cnt].push_back(b);
a[b].push_back(cnt);
}
a[cnt].push_back(x);
a[x].push_back(cnt);
}
}
else{
low[x]=min(low[x],dfn[y]);
}
}
}
signed main(){
ios::sync_with_stdio(false);
cin>>n>>m;
cnt=n;
for(int i=1;i<=m;i++){
cin>>u>>vv;
v[u].push_back(vv);
v[vv].push_back(u);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
tarjan(i);
top--;
}
}
return 0;
}