连通性问题(无向图)(未完结)
边双连通分量
我们首先定义两种边:返祖边为从一个点指向其祖先的边;横叉边从某个点指向树中另一个子树中的点的边。两者统称为非树边。而剩下的边即为树边,树边也就是再搜索树上的边。
考虑设
如果对于一个点
代码:
void tar(int u,int fa){
dfn[u]=low[u]=++tot;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(!dfn[j]){
tar(j,i);
if(low[j]>dfn[u]){
bri[i]=bri[i^1]=1;
}
low[u]=min(low[u],low[j]);
}
else if(i!=(fa^1))low[u]=min(low[u],dfn[j]);
}
}
接下来考虑一个事情,两个边双连通分量之间显然不能经过割边,于是我们跑一个
void dfs(int u,int c){
col[u]=c;
res[c].push_back(u);
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(col[j]||bri[i])continue;
dfs(j,c);
}
}
点双连通分量
如果对于一个点
求割点代码:
void tar(int u,int fa){
dfn[u]=low[u]=++tot;
int cnt=0;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(!dfn[j]){
tar(j,fa);
low[u]=min(low[u],low[j]);
if(low[j]>=dfn[u]){
cnt++;
if(u!=fa||cnt>1)cut[u]=1;
}
}
else low[u]=min(low[u],dfn[j]);
}
}
首先注意,割点属于多个点双连通分量内。
我们考虑用一个栈记录之前经过的点,如果发现当前点
注意特判孤立点。
代码:
void tar(int u,int fa){
dfn[u]=low[u]=++tot;
stk[++top]=u;
int son=0;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(!dfn[j]){
son++;
tar(j,u);
low[u]=min(low[u],low[j]);
if(low[j]>=dfn[u]){
cnt++;
int y;
do{
y=stk[top--];
res[cnt].push_back(y);
}while(stk[top+1]!=j);
res[cnt].push_back(u);
}
}
else{
low[u]=min(low[u],dfn[j]);
}
}
if(fa==0&&son==0)res[++cnt].push_back(u);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】