如有错误欢迎指出, 万分感谢.
#include<stdio.h>
#include<stack>
using namespace std;
const int maxn = 1e5 + 5;
stack<int> s;
bool iscut[maxn];
int idx, cnt, btot;
int h[maxn];
int low[maxn], dfn[maxn];
int scc[maxn], bcc[maxn];
struct edge
{
int nxt, v;
}e[maxn * 2];
//强连通分量
void tarjan(int u)
{
low[u] = dfn[u] = ++ idx;
s.push(u);
for (int i = h[u]; i; i = e[i].nxt)
{
int v = e[i].v;
if(!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
else if(!scc[v]) low[u] = min(low[u], dfn[v]);
}
if(low[u] == dfn[u])
{
cnt ++;
while(true)
{
int x = s.top();
scc[x] = cnt, s.pop();
if(x == u) break;
}
}
}
//割点
void tarjan(int u, int fa)
{
int child = 0;
low[u] = dfn[u] = ++ idx;
for (int i = h[u]; i; i = e[i].nxt)
{
int v = e[i].v;
if(!dfn[v])
{
child ++;
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u]) iscut[u] = true;
}
else if(dfn[v] < dfn[u] && v != fa)
low[u] = min(low[u], dfn[v]);
}
if(child == 1 && fa < 0) iscut[u] = false;
}
//点双连通分量
void tarjan(int u, int fa)
{
dfn[u] = low[u] = ++ idx;
for (int i = h[u]; i; i = e[i].nxt)
{
int v = e[i].v;
if(!dfn[v])
{
s.push(i);
tarjan(v, u);
if(low[v] >= low[u])
{
btot ++;
while(true)
{
int x = s.top(); s.pop();
bcc[x] = bcc[x ^ 1] = btot;
if(x == i) break;
}
//another edition
/*-----------------------------------------------------------------------
while(1){
int x = sta[topp--] ;
if(bccno[ P[x].fr ] != Bcc_cnt){
bcc[ Bcc_cnt ].push_back( P[x].fr ) ; bccno[ P[x].fr ] = Bcc_cnt ;
}
if(bccno[ P[x].to ] != Bcc_cnt){
bcc[ Bcc_cnt ].push_back( P[x].to ) ; bccno[ P[x].to ] = Bcc_cnt ;
}
if(x == i) break ;
}
------------------------------------------------------------------------*/
}
}
else if(dfn[v] < dfn[u] && v != fa)
s.push(i),
low[u] = min(low[u], dfn[v]);
}
}
//割边
int num = 1;
void tarjan(int u, int fa)
{
int child = 0;
low[u] = dfn[u] = ++ idx;
for (int i = h[u]; i; i = e[i].nxt)
{
int v = e[i].v;
if(!dfn[v])
{
child ++;
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(low[v] > dfn[u]) iscut[i] = iscut[i ^ 1] = true;
}
else if(dfn[v] < dfn[u] && v != fa)
low[u] = min(low[u], dfn[v]);
}
}
//边双连通分量 同强连通分量
void tarjan(int u, int fa)
{
for (int i = h[u]; i; i = e[i].nxt)
{
int v = e[i].v;
if(!dfn[v]) tarjan(v, u), low[u] = min(low[u], low[v]);
else if(dfn[v] < dfn[u] && v != fa)
low[u] = min(low[u], dfn[v]);
}
if(low[u] == dfn[u])
{
cnt ++;
while(true)
{
int x = s.top();
bcc[x] = cnt, s.pop();
if(x == u) break;
}
}
}
/*----------------------------------------
同样可以标记出所有桥, 然后dfs不经过桥即可
----------------------------------------*/
int main(){}