tarjan板子(割点割边连通分量)
2017-10-08 12:18
295 查看
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; } } }
相关文章推荐
- 强连通分量和桥和割点——Tarjanの板子
- tarjan 边连通分量+2-sat 模板
- POJ1236 Tarjan求强连通分量
- poj 3180 The Cow Prom(强连通分量 Tarjan)
- King's Quest - POJ 1904 Tarjan强连通分量
- 强连通分量(Korasaju、Tarjan)
- Tarjan求解有向图强连通分量的线性时间的算法
- tarjan求强连通分量专题
- [poj 2553]The Bottom of a Graph[Tarjan强连通分量]
- 强连通分量及缩点tarjan算法解析
- hdu1269 Tarjan强连通分量 模板(转)
- hdu1269迷宫城堡(tarjan求强连通分量模板)
- 图论算法(6) --- Tarjan算法求强连通分量
- 强连通分量 ( Tarjan,邻接链表 )——The Bottom of a Graph ( POJ 2553 )
- 由 USACO2003 Popular Cows[受欢迎的奶牛] 认识 Tarjan 求强连通分量并缩点
- BZOJ 1179: [Apio2009]Atm Tarjan强连通分量缩点,SPFA,DP
- USACO Section 5.3 Network of Schools - 回顾Tarjan求强连通分量
- POJ1236强连通分量tarjan
- 有向图强连通分量Tarjan
- [poj 2186]Popular Cows[Tarjan强连通分量]