先说一下强连通分量是个什么鬼吧。
说白了,就是在有向图的子图中任意两个点A B,A可以到B且 B可以到A就是强连通分量了。
原谅我的语文差到措辞措到没逻辑
我就说一下我常用的两种算法吧...代码丑什么的请见谅。
Tarjan:(具体内容请见上一篇blog中间部分【又懒得给链接】)
...说白了就是缩点..???
QAQ解释不清楚直接给代码算了_(:з」∠)_
void dfs(int u)
{
dfn[u]=low[u]=++cnt;inq[u]=1;ss.push(u);
for(int i=0;i<a[u].size();i++)
if(!dfn[a[u][i]])
{
dfs(a[u][i]);
low[u]=min(low[u],low[a[u][i]]);
}
else if(inq[a[u][i]]) low[u]=min(low[u],dfn[a[u][i]]);
if(dfn[u]==low[u])
{
int r=0;ct++;
while(r!=u&&!ss.empty())
{
r=ss.top();
inq[r]=0;
v[r]=ct;
ss.pop();
}
}
}
还有一种算法然而我自己都不知道那叫什么..QWQ
反正就是先dfs一遍后序存标号然后把边反向从标号最大的开始dfs..怎么我解释起来就那么迷之抽象呢
不管了不管了直接给代码算了
void dfs1(int u)
{
v[u]=1;
for(int i=0;i<a[u].size();i++)
if(!v[a[u][i]]) dfs1(a[u][i]);
c[++cnt]=u;
}
void dfs2(int u)
{
v[u]=q[u]=1;ss[++s]=u;
for(int i=0;i<b[u].size();i++)
if(!v[b[u][i]]) dfs2(b[u][i]);
}
for(i=0;i<n*4;i++)
if(!v[i]) dfs1(i);
for(i=0;i<n*4;i++)
for(j=0;j<a[i].size();j++)
b[a[i][j]].push_back(i);
memset(v,0,sizeof(v));
for(i=n*4;i>0;i--)
if(!v[c[i]])
{
s=0;memset(q,0,sizeof(q));
dfs2(c[i]);
for(j=1;j<=s;j++)
if((ss[j]<n*2&&q[ss[j]+n*2])||(ss[j]>=n*2&&q[ss[j]-n*2])) {f=1;break;}
if(f) break;
}
由于只是判断有没有解所以写得特别丑陋所以各位将就着看吧...
一些题目(待填坑):

3万+

被折叠的 条评论
为什么被折叠?



