首先让我先来说一说关于强连通分量的一些疑惑
1、当我已经知道了我要走的下一步节点在栈中,我能不能把比较中的DFN写成LOW?
2、如果low[v]>=dfn[u],此时u就是割点,这个东西怎么证明?
这里链接两篇Tarjan算法写的非常好的博客:
↑洛谷有模板
下面是鄙人写的裸的Tarjan求图中强连通分量的代码!
//Tarjan基本的算法实现
#include<bits/stdc++.h>
using namespace std;
struct sd{
int v,next;
}edge[1001];
int DFN[1001],LOW[1001];
int stk[1001],head[1001],vis[1001],cnt,tot,index,n,m;
void add(int x,int y)
{//链式前向星
edge[++cnt].next=head[x];
edge[cnt].v=y;
head[x]=cnt;return;
}
void tarjan(int x)
{
DFN[x]=LOW[x]=++tot;
stk[++index]=x;
vis[x]=1;
for(int i=head[x];i;i=edge[i].next)
{
if(!DFN[edge[i].v])
tarjan(edge[i].v),LOW[x]=min(LOW[x],LOW[edge[i].v]);
else if(vis[edge[i].v])
LOW[x]=min(LOW[x],DFN[edge[i].v]);
}
if(DFN[x]==LOW[x])
{
while(stk[index]!=x)
printf("%d ",stk[index]),vis[stk[index]]=0,index--;
printf("%d
",stk[index]),vis[stk[index]]=0,index--;
}
}
int main()
{
scanf("%d%d",&n,&m);
int x,y;
for(int i=1;i<=m;++i)
{
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=1;i<=n;++i)
{
if(!DFN[i]) tarjan(i);
}
return 0;
}
/*
6 8
1 2
1 4
2 3
3 6
2 5
5 6
4 5
5 1
*/
下面是我给出的求割点的tarjan算法程序。我还是有一些东西没有搞懂。(带有注释)
这里给一张图方便理解:(红色的是DFN,蓝色的是LOW)
//tarjan算法求割点,我好像自己也不是很懂
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
struct sd{
int next,v;
}edge[2*N];
int head[N],DFN[N],LOW[N],cnt=0,tot=0,n,m;
bool judge[N];
void add(int x,int y)
{
edge[++cnt].next=head[x];
edge[cnt].v=y;
head[x]=cnt;
}
void tarjan(int x,int fa)
{
int child=0;
DFN[x]=LOW[x]=++tot;
for(int i=head[x];i;i=edge[i].next)
{
int v=edge[i].v;//v是要到达的点
if(!DFN[v])
{
tarjan(v,fa);
LOW[x]=min(LOW[x],LOW[v]);
if(LOW[v]>=DFN[x]&&x!=fa)judge[x]=true;//就是说明下一个点的最早能追溯到的节点比当前点的dfs序大或等于
if(x==fa)child++;//找回来了,说明已经遍历完了一颗子树
}
LOW[x]=min(LOW[x],DFN[v]);//?? 判断回边因为是无向图!!!这里不能改的过于大了不能改成LOW否则容易出问题!
}
if(child>=2&&x==fa)judge[x]=true;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
for(int i=1;i<=n;++i)
if(!DFN[i])tarjan(i,i);
int ans=0;
for(int i=1;i<=n;++i)
if(judge[i])ans++;printf("%d
",ans);
for(int i=1;i<=n;++i)
if(judge[i])printf("%d ",i);
return 0;
}
By njc