http://poj.org/problem;jsessionid=57CE7F39567FF9BFA128CDB4A2E8D728?id=2553

第一道强连通分量题,tarjan算法+缩点,,输出出度为0的顶点。。。

//强连通分量为搜索树中的一颗子树
//stack自定义栈,dfn(u)为结点u的次序编号
//low(u)为u或u的子树能够追溯到的最早的栈中结点的次序号
//belong[u]为u所属连通分量
#include<iostream>
#include<string.h>
#include<algorithm>
#include<string>
#define N 5005
using namespace std;
bool istack[N];
int stack[N],dfn[N],low[N],belong[N],head[N],out[N];
typedef struct str
{ int to;
   int next;
}Node;
Node node[N*3];
int top,num,res,index,n;
void init()
{ 
	memset(head,-1,sizeof(head));
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	memset(out,0,sizeof(out));
	memset(istack,false,sizeof(istack));
	num=top=res=0;index=1;
}
void dfs(int i)
{
	dfn[i]=low[i]=index++;
	 stack[top++]=i;
	 istack[i]=true;
	 for(int j=head[i];j!=-1;j=node[j].next)
	 {
		  int v=node[j].to;
		  if(!dfn[v])
		  {
			  dfs(v);
			  if(low[v]<low[i]) low[i]=low[v];
		  }
		  else if(istack[v]&&dfn[v]<low[i])
			   low[i]=dfn[v];
	 }
	 int u;
	 if(dfn[i]==low[i])//回溯,以i为根的搜索子树上的所有结点是一个强连通分量
	 {   
		 res++;
		 do{
			  u=stack[--top];
			  istack[u]=false;
			  belong[u]=res;
		 }while(i!=u);
	}
}
void tarjan()
{
	for(int i=1;i<=n;++i)
		if(!dfn[i]) dfs(i);
}
void solve()//缩点
{
	for(int i=1;i<=n;++i)
	{
		for(int j=head[i];j!=-1;j=node[j].next)
			if(belong[i]!=belong[node[j].to])
			{
				out[belong[i]]++;
				break;
			}
	}
	for(int i=1;i<=n;++i)
		if(!out[belong[i]])
			cout<<i<<" ";
	        cout<<endl;
}
int main()
{   int m;
	while(cin>>n>>m&&n)
	{
		init();
		for(int i=0;i!=m;++i)
		{  int a,b;
		    cin>>a>>b;
			node[num].to=b;
			node[num].next=head[a];
			head[a]=num++;
		}
		tarjan();
		solve();
	}return 0;
}


你可能感兴趣的:(http://poj.org/problem;jsessionid=57CE7F39567FF9BFA128CDB4A2E8D728?id=2553)