Tarjan连通性算法模板大整合
更新日志
前言
由于Tarjan算法页面过多,这里统一做一个整合,后期可能还会加入或者更改这里的模板。
另外的,这个页面只提供模板——以及链接,详细讲解点链接即可。
强连通
(有向图,储存每个节点属于的分量编号)
int scnt;
int scc[N],siz[N];
int dcnt;
int dfn[N],low[N];
bool ins[N];
stack<int> stk;
void tarjan(int rt){
low[rt]=dfn[rt]=++dcnt;
stk.push(rt);ins[rt]=true;
for(int i=hd[rt];i;i=ne[i]){
if(!dfn[to[i]]){
tarjan(to[i]);
low[rt]=min(low[rt],low[to[i]]);
}
else if(ins[to[i]])low[rt]=min(low[rt],dfn[to[i]]);
}
if(dfn[rt]==low[rt]){
scnt++;
while(true){
int tp=stk.top();stk.pop();
ins[tp]=false;
scc[tp]=scnt;
siz[scnt]++;
if(tp==rt)break;
}
}
}
割点
(无向图,布尔数组判断割点+vector
存储割点)
int dcnt;
int dfn[N],low[N];
bool flag[N];
veci spl;
void tarjan(int rt,int fa){
dfn[rt]=low[rt]=++dcnt;
int ccnt=0;flag[rt]=false;
for(int e=hd[rt];e;e=ne[e]){
int nxt=to[e];
if(!dfn[nxt]){
ccnt++;
tarjan(nxt,rt);
low[rt]=min(low[rt],low[nxt]);
if(!flag[rt]&&low[nxt]>=dfn[rt]&&rt!=fa){
spl.push_back(rt);
flag[rt]=true;
}
}else low[rt]=min(low[rt],dfn[nxt]);
}
if(!flag[rt]&&rt==fa&&ccnt>=2){
spl.push_back(rt);
flag[rt]=true;
}
}
割边
(无向图,布尔数组判断桥)
int dcnt;
int dfn[N],low[N];
bool bri[M];
void tarjan(int now,int fed){
dfn[now]=low[now]=++cnt;
for(int e=hd[now];e;e=ne[e]){
int nxt=to[e],eid=(e-1)/2+1;
if(!dfn[nxt]){
tarjan(nxt,eid);
low[now]=min(low[now],low[nxt]);
if(low[nxt]>dfn[now]){
bri[eid]=true;
}
}else if(eid!=fed)low[now]=min(low[now],dfn[nxt]);
}
}
点双
(无向图,vector
储存连通分量所有节点编号)
int dcnt;
int dfn[N],low[N];
bool flag[N];
stack<int> stk;
int bcnt;
vector<int> bcc[N];
void tarjan(int x,int fa){
dfn[x]=low[x]=++dcnt;
stk.push(x);
int ccnt=0;
for(int e=hd[x];e;e=ne[e]){
int nxt=to[e];
if(!dfn[nxt]){
++ccnt;
tarjan(nxt,x);
low[x]=min(low[x],low[nxt]);
if(low[nxt]>=dfn[x]){
++bcnt;
while(1){
int tp=stk.top();stk.pop();
bcc[bcnt].push_back(tp);
if(tp==nxt)break;
}
bcc[bcnt].push_back(x);
}
}else low[x]=min(low[x],dfn[nxt]);
}
if(x==fa&&ccnt==0){
++bcnt;
bcc[bcnt].push_back(x);
}
}
边双
(无向图,vector
储存连通分量所有节点编号)
int dcnt;
int dfn[N],low[N];
int scnt;
vector<int> scc[N];
stack<int> stk;
void tarjan(int x,int fed){
dfn[x]=low[x]=++dcnt;
stk.push(x);
for(int e=hd[x];e;e=ne[e]){
int nxt=to[e];
if(!dfn[nxt]){
tarjan(nxt,(e-1)/2+1);
low[x]=min(low[x],low[nxt]);
}else if(fed!=(e-1)/2+1)low[x]=min(low[x],dfn[nxt]);
}
if(low[x]>=dfn[x]){
++scnt;
while(1){
int tp=stk.top();stk.pop();
scc[scnt].push_back(tp);
if(tp==x)break;
}
}
}