老是搞不清他们的关系,不知道该用那份代码,今天理了一下,整理一下模板
点连通分量:可以求出点连通分量包含哪些点,那个点属于那个连通分量
struct edge
{
int u,v;
};
int pre[maxn],iscut[maxn],bccno[maxn],dfs_clock,bcc_cnt;
vector<int> G[maxn],bcc[maxn];
stack<edge> s;
int n;
int dfs(int u,int fa)
{
int lowu=pre[u]=++dfs_clock;
int child=0;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
edge e=edge{u,v};
if(!pre[v])
{
s.push(e);
child++;
int lowv=dfs(v,u);
lowu=min(lowu,lowv);
if(lowv>=pre[u])
{
iscut[u]=true;
bcc_cnt++;bcc[bcc_cnt].clear();
while(true)
{
edge x=s.top();s.pop();
if(bccno[x.u]!=bcc_cnt){bcc[bcc_cnt].push_back(x.u);bccno[x.u]=bcc_cnt;}
if(bccno[x.v]!=bcc_cnt){bcc[bcc_cnt].push_back(x.v);bccno[x.v]=bcc_cnt;}
if(x.u==u&&x.v==v)break;
}
}
}
else if(pre[v]<pre[u]&&v!=fa)
{
s.push(e);
lowu=min(lowu,pre[v]);
}
}
if(fa<0&&child==1)iscut[u]=0;
return lowu;
}
void find_bcc(int m)
{
memset(pre,0,sizeof(pre));
memset(iscut,0,sizeof(iscut));
memset(bccno,0,sizeof(bccno));
dfs_clock=bcc_cnt=0;
for(int i=0;i<=m;i++)
if(!pre[i])dfs(i,-1);
}
边连通分量:点连通分量是找到一个割点后,把栈里的点划分到联通分量里,而边连通分量是所有孩子处理完了,才划分
struct edge
{
int u,v;
};
int pre[maxn],low[maxn],iscut[maxn],bccno[maxn],dfs_clock,bcc_cnt;
int deg[maxn];
vector<int> grid[maxn],bcc[maxn];
stack<int> s;
void dfs(int u,int fa)
{
pre[u]=low[u]=++dfs_clock;
s.push(u);
int biao=0;
for(int j=0; j<grid[u].size(); j++)
{
int v=grid[u][j];
if(!pre[v])
{
dfs(v,u);
low[u]=min(low[v],low[u]);
}
else if(pre[v]<pre[u]&&v!=fa)
low[u]=min(low[u],pre[v]);
}
if(pre[u]==low[u])
{
int j;
bcc_cnt++;
do
{
j=s.top();s.pop();
bccno[j]=bcc_cnt;
}
while(j!=u);
}
}
割点和桥:
void dfs(int u,int fa)
{
low[u]=pre[u]=++dfs_clock;
int child=0;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(!pre[v])
{
child++;
dfs(v,u);
low[u]=min(low[v],low[u]);
if(low[v]>=pre[u])
iscut[u]=true;
}
else if(pre[v]<pre[u]&&v!=fa)
low[u]=min(low[u],pre[v]);
}
if(fa<0&&child==1)iscut[u]=false;
}
有向图强连通分量:
vector<int> grid[maxn];
int lowlink[maxn],pre[maxn],sccno[maxn],dfs_clock,scc_cnt;
stack<int> s;
void dfs(int u)
{
pre[u]=lowlink[u]=++dfs_clock;
s.push(u);
for(int i=0;i<grid[u].size();i++)
{
int v=grid[u][i];
if(!pre[v])
{
dfs(v);
lowlink[u]=min(lowlink[u],lowlink[v]);
}
else if(!sccno[v])
{
lowlink[u]=min(lowlink[u],pre[v]);
}
}
if(lowlink[u]==pre[u])
{
scc_cnt++;
while(true)
{
int x=s.top();s.pop();
sccno[x]=scc_cnt;
if(x==u)break;
}
}
}
bool find_scc()
{
dfs_clock=scc_cnt=0;
memset(sccno,0,sizeof(sccno));
memset(pre,0,sizeof(pre));
while(!s.empty())s.pop();
dfs(1);
for(int i=1;i<=n;i++)
if(!pre[i])dfs(i);
if(scc_cnt>1)return false;
return true;
}