tarjan板子(割点割边连通分量)
来源:互联网 发布:怪兽汉化 知乎 编辑:程序博客网 时间:2024/05/17 02:09
low函数实际上可以不开成数组的(话是这么说,但是会占用栈空间,所以说还是老老实实写成静态数组开在外面比较好)。
割点:
void tarjan_point(int i,int fd)//给边上标号来判定重边{ dfn[i]=low[i]=++dfs_clock; int j,id,chd=0; for(int p=first[i];p;p=E[p].next) { j=E[p].to,id=E[p].id; if(dfn[j]) { if(dfn[j]<dfn[i]&&id!=fd) low[i]=min(low[i],dfn[j]);//利用返祖边更新low函数 continue; } chd++; tarjan_point(j,id); if(low[j]>=dfn[i]) mark[i]=1;//只要i有一个儿子满足lowj>=dfni就说明i是割点 low[i]=min(low[i],low[j]);//利用树边更新low函数 } if(fd==0&&chd==1) mark[i]=0;//对于开始遍历的根结点需要特殊判断,可能这个点不是割点 }
割边:
void tarjan_edge(int i,int fd)//给边上标号来判定重边{ dfn[i]=low[i]=++dfs_clock; int j,id; for(int p=first[i];p;p=E[p].next) { j=E[p].to,id=E[p].id; if(dfn[j]) { if(dfn[j]<dfn[i]&&id!=fd) low[i]=min(low[i],dfn[j]);//利用返祖边更新low函数 continue; } tarjan_edge(j,id); low[i]=min(low[i],low[j]);//和儿子的连边更新low函数 if(low[j]==dfn[j]) { a[++cnt]=(data){min(i,j),max(i,j)}; mark[id]=1;//改成判定这一条指向儿子的边是不是割边,此写法也不受重边的影响。 } }}
边双连通分量:
void tarjan_edge(int i,int fd){ dfn[i]=low[i]=++dfs_clock; stk[++top]=i; int j,id; for(int p=first[i];p;p=E[p].next) { j=E[p].to,id=E[p].id; if(dfn[j]) { if(dfn[j]<dfn[i]&&id!=fd) low[i]=min(low[i],dfn[j]); continue; } tarjan_edge(j,id); low[i]=min(low[i],low[j]); if(low[j]==dfn[j])//第一次发现割边就应该算成一个边双连通分量 { mark[id]=1; ebc_cnt++; while(1) { int x=stk[top--]; ebc[ebc_cnt]++; ebcno[x]=ebc_cnt; if(x==j) break; } MAX_ebc=max(MAX_ebc,ebc[ebc_cnt]); } } if(!fd&&top)//改了写法之后需要特殊处理遍历树的根结点 { ebc_cnt++; while(top) { int x=stk[top--]; ebc[ebc_cnt]++; ebcno[x]=ebc_cnt; } MAX_ebc=max(MAX_ebc,ebc[ebc_cnt]); }}
点双连通分量(割点的分量标号没什么意义):
void tarjan_point(int i,int fd){ dfn[i]=low[i]=++dfs_clock; stk[++top]=i; int j,id,chd=0; for(int p=first[i];p;p=E[p].next) { j=E[p].to,id=E[p].id; if(dfn[j]) { if(dfn[j]<dfn[i]&&fd!=id) low[i]=min(low[i],dfn[j]); continue; } chd++; tarjan_point(j,id); low[i]=min(low[i],low[j]); if(low[j]>=dfn[i])//注意判定条件和边双连通分量的区别 { mark[i]=1; bcc_cnt++; bcc[bcc_cnt]++; bccno[i]=0; while(1) { int x=stk[top--]; bcc[bcc_cnt]++; bccno[x]=bcc_cnt; if(x==j) break; } MAX_bcc=max(MAX_bcc,bcc[bcc_cnt]); } } if(fd==0&&chd==1) mark[i]=0;}
强连通分量:
void tarjan_scc(int i){ dfn[i]=low[i]=++dfs_clock; stk[++top]=i; for(int p=first[i];p;p=E[p].next) { int j=E[p].to; if(dfn[j]) { if(!sccno[j]) low[i]=min(low[i],dfn[j]);//反向边更新low函数 continue; } tarjan_scc(j); low[i]=min(low[i],low[j]); } if(low[i]==dfn[i]) { scc_cnt++; while(1) { int x=stk[top--]; sccno[x]=scc_cnt; if(x==i) break; } }}
阅读全文
1 0
- tarjan板子(割点割边连通分量)
- Tarjan求强连通分量板子
- 强连通分量(Tarjan)
- 强连通分量板子
- tarjan 算法模板(边连通分量)
- 强连通分量(tarjan算法)
- tarjan算法求图中环(强连通分量)
- Tarjan算法(求强连通分量)
- hdu1827 强连通分量tarjan(初战)
- 强连通分量(Korasaju、Tarjan)
- tarjan算法模板(强连通分量)
- 强连通分量(Tarjan、Kosaraju)
- 强连通分量SCC(Tarjan)
- tarjan 算法(求强连通分量)
- 强连通分量tarjan
- 强连通分量 Tarjan
- Tarjan强连通分量
- 强连通分量-Tarjan
- python里使用正则表达式的连接符
- MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作
- Lesson 2:作业4:编写代码模拟手机与SIM卡的组合关系。
- mac 安全 没有允许任何来源
- 总结c语言操作符
- tarjan板子(割点割边连通分量)
- 对原生态jdbc程序中的问题总结
- JAVA数值四舍五入
- [NLP]如何进行情感分析
- 用construct2编写一个简单的游戏
- leetcode 377. Combination Sum IV 组合之和 + DP动态规划 + DFS深度优先遍历
- 维护篇 19. 升级到5.2版固件后不能保存日志 ❀ 飞塔 (Fortinet) 防火墙
- caffe学习例子(一) mnist手写字识别
- nginx 负载均衡