tarjan模板
仅供个人查看,无法验证其正确性
//************************************************************ void v_dcc_tarjan(int x) //无向图->点双联通分量(找割点) { low[x]=dfn[x]=++indx; int flag=0; for(Reg int i=fir[x];i;i=lian[i].next) { if(!dfn[lian[i].ed]) { v_dcc_tarjan(lian[i].ed); low[x]=min(low[x],low[lian[i].ed]); if(low[lian[i].ed]>=dfn[x]) { ++flag; if(x!=root||flag>1) cur[x]=1; } } else low[x]=min(low[x],dfn[lian[i].ed]); } return; } //************************************************************ void v_dcc_tarjan(int x) //无向图->点双联通分量(找点双联通) { low[x]=dfn[x]=++indx; stack[++stack[0]]=x; int flag=0; if(x==root&&!fir[x]) v_dcc[++cnt].push_back(x); else for(Reg int i=fir[x];i;i=lian[i].next) { if(!dfn[lian[i].ed]) { v_dcc_tarjan(lian[i].ed); low[x]=min(low[x],low[lian[i].ed]); if(low[lian[i].ed]>=dfn[x]) { ++flag; if(x!=root||flag>1) cur[x]=1; ++cnt; while(stack[stack[0]]!=lian[i].ed) v_dcc[cnt].push_back(stack[stack[0]--]); v_dcc[cnt].push_back(stack[stack[0]--]); v_dcc[cnt].push_back(x); } } else low[x]=min(low[x],dfn[lian[i].ed]); } return; } void v_dcc_union() //无向图->点双联通分量(缩点) { int num=cnt; for(Reg int i=1;i<=n;++i) if(cur[i]) pos[i]=++num; for(Reg int i=1;i<=cnt;++i) { for(Reg int j=0,x;j<v_dcc[i].size();++j) { x=v_dcc[i][j]; if(cur[x]) {add(pos[x],i); add(i,pos[x]);} else pos[x]=i; } } cnt=num; return; } //************************************************************ void e_dcc_tarjan(int x,int fa) //无向图->边双联通分量(找桥、割边) { low[x]=dfn[x]=++indx; for(Reg int i=fir[x];i;i=lian[i].next) { if(lian[i].ed==fa) continue; if(!dfn[lian[i].ed]) { e_dcc_tarjan(lian[i].ed,x); low[x]=min(low[x],low[lian[i].ed]); if(low[lian[i].ed]>dfn[x]) lian[i].cur=lian[i^1].cur=1; //要改两条边,具体情况具体修改 } else low[x]=min(low[x],dfn[lian[i].ed]); } return; } //************************************************************ void e_dcc_tarjan(int x,int fa) //无向图->边双联通分量(找边双联通) { low[x]=dfn[x]=++indx; stack[++stack[0]]=x; for(Reg int i=fir[x];i;i=lian[i].next) { if(lian[i].ed==fa) continue; if(!dfn[lian[i].ed]) { e_dcc_tarjan(lian[i].ed,x); low[x]=min(low[x],low[lian[i].ed]); } else low[x]=min(low[x],dfn[lian[i].ed]); } if(low[x]==dfn[x]) { ++cnt; while(stack[stack[0]]!=x) { pos[stack[stack[0]]]=cnt; e_dcc[cnt].push_back(stack[stack[0]--]); } pos[stack[stack[0]]]=cnt; e_dcc[cnt].push_back(stack[stack[0]--]); } return; } void e_dcc_union() //无向图->边双联通分量(缩点) { for(Reg int i=1;i<=tot;++i) if(pos[lian[i].st]!=pos[lian[i].ed]) add(pos[lian[i].st],pos[lian[i].ed]); return; } //************************************************************ void scc_tarjan(int x) //有向图->强联通分量(找强联通) { low[x]=dfn[x]=++indx; stack[++stack[0]]=x; ins[x]=1; for(Reg int i=fir[x];i;i=lian[i].next) { if(!dfn[lian[i].ed]) { scc_tarjan(lian[i].ed); low[x]=min(low[x],low[lian[i].ed]); } else if(ins[lian[i].ed]) low[x]=min(low[x],dfn[lian[i].ed]); } if(low[x]==dfn[x]) { ++cnt; while(stack[stack[0]]!=x) { pos[stack[stack[0]]]=cnt; scc[cnt].push_back(stack[stack[0]--]); } pos[stack[stack[0]]]=cnt; scc[cnt].push_back(stack[stack[0]--]); } return; } void scc_union() //有向图->强联通分量(缩点) { for(Reg int i=1;i<=tot;++i) if(pos[lian[i].st]!=pos[lian[i].ed]) add(pos[lian[i].st],pos[lian[i].ed]); return; } //************************************************************