tarjan算法讲解

 

附一段代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>

using namespace std;

struct node {
	int v,next;
} edge[1001];

int DFN[1001],LOW[1001];
int stack[1001],heads[1001],visit[1001],cnt,tot,index;

void add(int x,int y) 
{
	edge[++cnt].next=heads[x];
	edge[cnt].v = y;
	heads[x]=cnt;
	return ;
}

void tarjan(int x) 
{ //代表第几个点在处理。递归的是点。
	DFN[x]=LOW[x]=++tot;// 新进点的初始化。
	stack[++index]=x;//进站
	visit[x]=1;//表示在栈里 
	for(int i=heads[x];~i;i=edge[i].next) 
	{
		int vv=edge[i].v;
		if(!DFN[edge[i].v]) 
		{//如果没访问过
			tarjan(edge[i].v);//往下进行延伸,开始递归
			LOW[x]=min(LOW[x],LOW[edge[i].v]);//递归出来,比较谁是谁的儿子/父亲,就是树的对应关系,涉及到强连通分量子树最小根的事情。
		} 
		else if(visit[edge[i].v]) 
		{ //如果访问过,并且还在栈里。
			LOW[x]=min(LOW[x],DFN[edge[i].v]);//比较谁是谁的儿子/父亲。就是链接对应关系
		}
	}
	if(LOW[x]==DFN[x]) 
	{ //发现是整个强连通分量子树里的最小根。
		do 
		{
			printf("%d ",stack[index]);
			visit[stack[index]]=0;
			index--;
		} while(x!=stack[index+1]);//出栈,并且输出。
		printf("\n");
	}
	return ;
}
int main() 
{
	memset(heads,-1,sizeof(heads));
	int n,m;
	scanf("%d%d",&n,&m);
	int xx,y;
	for(int i=1;i<=m;i++) 
	{
		scanf("%d%d",&xx,&y);
		add(xx,y);
	}
	for(int i=1;i<=n;i++)
		if(!DFN[i])  
			tarjan(i);//当这个点没有访问过,就从此点开始。防止图没走完
	return 0;
}
/*
6 8
1 4
1 2
2 5 
2 3
3 6
4 5
5 1
5 6

*/

  

posted @ 2017-04-11 17:40  ioioioioioio  阅读(968)  评论(0编辑  收藏  举报