poj 2553 缩点,求出度为0 的点连通块中的点

#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
const int MAX = 10010;
vector<int> edge[MAX];
int st[MAX];
int dfn[MAX],low[MAX];
int top,btype,tdfn;//btype:连通块的个数
int belong[MAX];//点属于哪个连通块
bool ins[MAX];
void dfs(int s)
{
	int i,t;
	dfn[s]=low[s]=++tdfn;
	ins[s]=true;
	st[++top]=s;
	for(i=0;i<edge[s].size();i++)
	{
		t=edge[s][i];
		if(!dfn[t])
		{
			dfs(t);
			if(low[t]<low[s]) low[s]=low[t];
		}
		else if(ins[t] && dfn[t]<low[s])  low[s]=dfn[t];
	}
	if(dfn[s]==low[s])
	{
		btype++;
		do
		{
			t=st[top--];
			ins[t]=false;
			belong[t]=btype;
		}while(t!=s);
	}
}
void SCC(int n)
{
	int i;
	top=btype=tdfn=0;
	memset(ins,false,sizeof(ins));
	memset(dfn,0,sizeof(dfn));
	for(i=1;i<=n;i++)
		if(!dfn[i])
			dfs(i);
}
int chu[MAX];
int ans[5010];
int main()
{
    int i,j;
	int n,m;
	int a,b;
	while(scanf("%d",&n),n)
	{
		for(i=0;i<=n;i++)
			edge[i].clear();
		scanf("%d",&m);
		for(i=0;i<m;i++)
		{
			scanf("%d%d",&a,&b);
			edge[a].push_back(b);
		}
		SCC(n);
		memset(chu,0,sizeof(chu));
		for(i=1;i<=n;i++)
		{
			int tmp=belong[i];
			for(j=0;j<edge[i].size();j++)
			{
				if(belong[i]!=belong[edge[i][j]])//一条边的两个点属于不同的连通块
					chu[tmp]++;
			}
		}
		int TOT=0;
		int flag=1;
		for(i=1;i<=btype;i++)
		{
			if(chu[i]==0)
			{
				flag=0;
				for(j=1;j<=n;j++)
				{
					if(belong[j]==i) 
						ans[TOT++]=j;
				}
			}
		}
		if(flag){  printf("\n\n");continue;}
		sort(ans,ans+TOT);
		for(i=0;i<TOT;i++)
		{
			if(i!=TOT-1)  printf("%d ",ans[i]);
			else printf("%d\n",ans[i]);
		}
	}
	return 0;
}

你可能感兴趣的:(poj)