割点求法
void tarjan(int x,int fa)
{int temp,a,sum=0;
low[x]=cnt[x]=++dfssum;
for(a=0;a<edge[x].size();a++)
{
temp=edge[x][a];
if(temp==fa)continue;//不能反向边
if(!cnt[temp])
{
sum++;//记录儿子个数
tarjan(temp,x);
low[x]=min(low[x],low[temp]);
if(x!=root&&low[temp]>=cnt[x])//注意是大于且等于
iscut[x]=1;//当成为一条链的时候说明为断点
}
else low[x]=min(low[x],cnt[temp]);
}
if(x==root&&sum>1)iscut[x]=1;//儿子数大于一为断点;
}
桥的求法
void tarjan(int x,int fa)
{
int temp;
low[x]=cnt[x]=++dfssum;
int sum=0;
for(int a=head[x]; a!=-1; a=edge[a].next)
{
temp=edge[a].fina;
if(temp==fa)continue;
if(!cnt[temp])
{
tarjan(temp,x);
low[x]=min(low[x],low[temp]);
if(low[temp]>cnt[x])//注意是大于不等于
{
brige++;
edge[a].cut=true;
edge[a^1].cut=true;
}
}
else if(low[x]>cnt[temp])
low[x]=cnt[temp];
}
}
边双联通
struct Edge{
int u,v;
Edge(int u=0,int v=0):u(u),v(v){}
}e[maxm];
int n,m,stamp,dfn[maxn],low[maxn],bccno[maxn],bcc_cnt;
vector
vec[maxn],bcc[maxn];
bool g[maxn][maxn],isbridge[maxm];
void tarjan(int index,int fa)
{
int tmp;
dfn[index]=low[index]=++stamp;
for(int i=0;i
dfn[index])
isbridge[vec[index][i]]=isbridge[vec[index][i]^1]=1;
}
else if(dfn[tmp]
点双联通
struct Edge{
int u,v;
Edge(int u=0,int v=0):u(u),v(v){}
}e[maxm];
int n,m,stamp,dfn[maxn],low[maxn],iscut[maxn],bccno[maxn];
int scnt,stack[maxm],bcc_cnt;
vector
vec[maxn],bcc[maxn];
void tarjan(int index,int fa)
{
int child=0,tmp;
dfn[index]=low[index]=++stamp;
for(int i=0;i
=dfn[index])
{
iscut[index]=1;
bcc[++bcc_cnt].clear();
while(1)
{
int num=stack[scnt--];
if(bccno[e[num].u]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(e[num].u);
bccno[e[num].u]=bcc_cnt;
}
if(bccno[e[num].v]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(e[num].v);
bccno[e[num].v]=bcc_cnt;
}
if(e[num].u==index && e[num].v==tmp)
break;
}
}
}
else if(dfn[tmp]