強連通分量(有向圖)
void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
stac[++top]=x;
vis[x]=1;
for(int i=hd[x];i;i=nxt[i])
{
int y=go[i];
if(!dfn[y])//樹邊
{tarjan(y);low[x]=min(low[x],low[y]);}
else if(vis[y])low[x]=min(low[x],dfn[y]);//在棧中(判橫叉邊)
}
if(low[x]==dfn[x])//出不去
{
col_cnt++;
while(stac[top+1]!=x){
c[stac[top]]=col_cnt;
vis[stac[top]]=0;
ve[col_cnt].push_back(stac[top]);
top--;
}
}
}
邊雙連通分量(無向圖)
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++cnt;
stac[++top]=u;
int son=0;
for(int i=hd[u];i;i=nxt[i])
{
int v=go[i];
if(!dfn[v])
{
son++;
tarjan(v,i);
low[u]=min(low[v],low[u]);
}
else if(i!=(fa^1)) low[u]=min(low[u],dfn[v]);//可以透過重邊走向父親
}
if(low[u]==dfn[u])
{
++col;
while(stac[top+1]!=u)
{
ans[col].push_back(stac[top--]);
}
}
return ;
}
點雙連通分量(無向圖)
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++cnt;
stac[++top]=u;
int son=0;
for(int i=hd[u];i;i=nxt[i])
{
int v=go[i];
if(!dfn[v])
{
son++;
tarjan(v,u);
low[u]=min(low[v],low[u]);
if(low[v]>=dfn[u])
{
++col;
while(stac[top+1]!=v)
{
ans[col].push_back(stac[top--]);
}
ans[col].push_back(u);//因為一個割點可能屬於多個點雙,所以不能出棧
}
}
else if(v!=fa) low[u]=min(low[u],dfn[v]);
}
if(fa==0&&son==0)ans[++col].push_back(u);//特判獨立點
return ;
}