Tarjan全家桶
强联通分量及缩点
#include<bits/stdc++.h>
#define re register
#define v e[i].to
using namespace std;
const int lzw=1e4+3;
int n,m,head[lzw],tot,h[lzw],cnt,dfn[lzw],low[lzw],belong[lzw],stk[lzw],top,dfn_clock,scc_cnt,in[lzw];
struct edge{
int to,next;
}e[lzw*10],ee[lzw*10];
void add(int a,int b){
e[++tot].to=b;
e[tot].next=head[a];
head[a]=tot;
}
void insert(int a,int b){
ee[++cnt].to=b;
ee[cnt].next=h[a];
h[a]=cnt;
}
void tarjan(int u){//强联通分量
dfn[u]=low[u]=++dfn_clock,stk[++top]=u;
for(re int i=head[u];i;i=e[i].next){
if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]);
else if(!belong[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]){
scc_cnt++;
while(1){
int tmp=stk[top--];
belong[tmp]=scc_cnt;
if(tmp==u) break;
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(re int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(re int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
for(re int j=1;j<=n;j++){//缩点
for(re int i=head[j];i;i=e[i].next){
if(belong[v]==belong[j]) continue;
insert(belong[j],belong[v]),in[belong[v]]++;
}
}
return 0;
}
割点
\(\large {\color{red} {注意判根!}}\)
void tarjan(int u,int fa){
dfn[u]=low[u]=++dfn_clock;
int ch=0;
for(re int i=head[u];i;i=e[i].next){
if(!dfn[v]){
tarjan(v,u),low[u]=min(low[v],low[u]);
if((!fa&&++ch>1)||(fa&&low[v]>=dfn[u])) cut[u]=1;
}
else if(v!=fa) low[u]=min(low[u],dfn[v]);
}
}
点双联通分量
void tarjan(int u,int fa){
dfn[u]=low[u]=++dfn_clock;
stk[++top]=u;
for(re int i=head[u];i;i=e[i].next){
if(v==fa) continue;
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]){
bcc_cnt++;
while(1){
int tmp=stk[top--];
all[bcc_cnt].push_back(tmp);
if(tmp==v) break;
}
all[bcc_cnt].push_back(u);
}
}else low[u]=min(low[u],dfn[v]);
}
}
桥
void tarjan(int u,int fa){
dfn[u]=low[u]=++dfn_clock;
for(re int i=head[u];i;i=e[i].next){
if(v==fa) continue;
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]) e[i].flag=e[i^1].flag=1;
}else low[u]=min(low[u],dfn[v]);
}
}
边双联通分量
桥的部分再加上\(DFS\)
void dfs(int u){
belong[u]=cnt,vis[u]=1;
for(re int i=head[u];i;i=e[i].next) if((!e[i].flag)&&(!vis[v])) dfs(v);
}
签名:
我将轻轻叹息,叙述这一切,
许多许多年以后:
林子里有两条路,我——
选择了行人稀少的那一条,
它改变了我的一生。