题意:
给一个定义bottom(G)={v∈V|∀w∈V:(v→w)⇒(w→v)},意思就是在一个有向图中存在一种点v1,这种点满足:v1可达的点集V中所有点,都有一条路径回到v1。先要找出所有的点,按字典序输出。
思路:
找到出度为0的强联通分量,按字典叙输出其中的点。
#include<iostream>
using namespace std;
const int MAXN =10001;
int DFN[MAXN];
int LOW[MAXN];
int instack[MAXN];
int Stap[MAXN];
int Belong[MAXN];
int num[MAXN];
int count[MAXN];
struct edge
{
int v,next;
}vetex[50001];
int head[MAXN];
int Stop,Bcnt,Dindex,N,k;
void add(int a,int b)
{
vetex[k].v = b;
vetex[k].next = head[a];
head[a] = k;k++;
}
void tarjan(int i)
{
int j;
DFN[i]=LOW[i]=++Dindex;
instack[i]=true;
Stap[++Stop]=i;
for (int k=head[i];k;k=vetex[k].next)
{
j=vetex[k].v;
if (!DFN[j])
{
tarjan(j);
if (LOW[j]<LOW[i])
LOW[i]=LOW[j];
}
else if (instack[j] && DFN[j]<LOW[i])
LOW[i]=DFN[j];
}
if (DFN[i]==LOW[i])
{
Bcnt++;
do
{
j=Stap[Stop--];
instack[j]=false;
Belong[j]=Bcnt;
}
while (j!=i);
}
}
void solve()
{
int i;
Stop=Bcnt=Dindex=0;
for (i=1;i<=N;i++)
if (!DFN[i])
tarjan(i);
}
int main()
{
int E;
while(cin>>N)
{
if(N==0)
break;
cin>>E;
k=1;
memset(count,0,sizeof(count));
memset(num,0,sizeof(num));
memset(head,false,sizeof(head));
memset(DFN,0,sizeof(DFN));
for(int i=1;i!=E+1;i++)
{
int a,b;cin>>a>>b;
add(a,b);
}
solve();
//cout<<Bcnt<<endl;
for(int i=1;i!=N+1;i++)
{
int t = Belong[i];
for(int k = head[i];k;k=vetex[k].next)
if(t!=Belong[vetex[k].v])
num[t]++;
if(num[t]!=0)
count[t]++;
}
//for(int i=1;i!=Bcnt+1;i++)
//cout<<count[i]<<" ";
int flag(0);
for(int i=1;i!=N+1;i++)
{
int t = Belong[i];
if(count[t]==0)
{
if(flag==0)
cout<<i;
else
cout<<" "<<i;
flag=1;
}
}
cout<<endl;
}
return 0;
}