无向图
Tarjan
求割点
if(low[v]>=dfn[x]){ if(x!=a&&x!=b&&dfn[x]<=low[b])ge[x]=true; } 求点双
求割边
求边双
点双缩点连图
边双缩点连图
缩点连图
有向图
Tarjan
强连通缩点
int a=0,b=0; for(int i=1;i<=cc;++i){ if(!in[i])a++; if(!out[i])b++; } if(cc==1)std::cout<<0< 代码
auto tarjan=[&](auto &&tarjan,int x)->void{ dfn[x]=low[x]=++tt;int ch=0; for(auto v:G[x]){ if(!dfn[v]){ tarjan(tarjan,v); low[x]=min(low[x],low[v]); if(low[v]>=dfn[x]){ ch++; if(x1!=rt||ch>1) ge[x]=true; } }else low[x]=min(low[x],dfn[v]); } if(rt==x&&ch==1)ge[x]=false; }; std::vector dfn(n+5,0),low(n+5,0);int tt=0; std::vector sz(n+5,0),col(n+5,0);int cc=0; std::stack st;std::vector> hs(n+5); std::vector ge(n+5,false);int rt=0; auto tarjan=[&](auto &&tarjan,int x)->void{ dfn[x]=low[x]=++tt;int ch=0; st.push(x); for(auto v:G[x]){ if(!dfn[v]){ tarjan(tarjan,v); low[x]=min(low[x],low[v]); if(low[v]>=dfn[x]){ ch++; if(x!=rt||ch>1){ ge[x]=true; } int y;cc++;//缩点 do{ y=st.top();st.pop(); col[y]=cc;sz[cc]++;hs[cc].push_back(y); }while(y!=v); hs[cc].push_back(x);sz[cc]++;//割点放入 } }else low[x]=min(low[x],dfn[v]); } }; for(int i=1;i<=n;++i)if(!dfn[i]){ rt=i; tarjan(tarjan,i); } std::vector dfn(n+5,0),low(n+5,0);int tt=0; std::vector sz(n+5,0),col(n+5,0);int cc=0; std::stack st;std::vector> hs(n+5); auto tarjan=[&](auto &&tarjan,int x,int p)->void{ dfn[x]=low[x]=++tt; st.push(x); for(auto [v,i]:G[x]){//i为边的编号 if(i==p)continue; if(!dfn[v]){ tarjan(tarjan,v,i); low[x]=min(low[x],low[v]); // if(low[v]>dfn[x]){ // std::cout< std::vector dfn(n+5,0),low(n+5);int tt=0; std::stack st;std::vector> hs(n+5); std::vector col(n+5,0),sz(n+5,0);int cc=0; auto tarjan=[&](auto &&tarjan,int x)->void{ dfn[x]=low[x]=++tt; st.push(x); for(auto v:G[x]){ if(!dfn[v]){ tarjan(tarjan,v); low[x]=min(low[x],low[v]); }else if(!col[v])low[x]=min(low[x],dfn[v]); } if(dfn[x]==low[x]){ ++cc; int y; do{ y=st.top();st.pop(); col[y]=cc;sz[cc]++;hs[cc].push_back(y); }while(y!=x); } }; for(int i=1;i<=n;++i){ if(!dfn[i])tarjan(tarjan,i); }