经典的强连通分量题,我用了Tarjan算法+缩点。把每个强连通分量缩点,求出每个点的出度。所谓的bottom,就是那些出度为0的强连通分量,对于所有出度不为零的连通分量里的点,都可以到达bottom中的点。
/******************************************************************************* # Author : Neo Fung # Email : [email protected] # Last modified: 2011-09-25 01:42 # Filename: ZOJ1979 POJ2553 The Bottom of a Graph.cpp # Description : ******************************************************************************/ // #include "stdafx.h" // #define DEBUG #include <fstream> #include <stdio.h> #include <iostream> #include <string.h> #include <string> #include <memory.h> #include <stack> #include <algorithm> #define MAX 5010 using namespace std; struct NODE { int to; NODE *next; }*v[MAX],node[MAX*5]; int n,e; stack<int> mstack; int inStack[MAX],dfn[MAX],low[MAX],whichComponent[MAX]; int dag_out[MAX]; int ind,componentNum,nodeind; void init(void) { ind=0; componentNum=0; nodeind=0; memset(v,'\0',sizeof(v)); memset(inStack,0,sizeof(inStack)); memset(dfn,-1,sizeof(dfn)); memset(low,-1,sizeof(low)); memset(whichComponent,0,sizeof(whichComponent)); memset(dag_out,0,sizeof(dag_out)); while(!mstack.empty())mstack.pop(); } void input(void) { int from,to; for(int i=0;i<e;++i) { scanf("%d %d",&from,&to); node[nodeind].to=to; node[nodeind].next=v[from]; v[from]=&node[nodeind++]; } } void tarjan(int i) { int to; dfn[i]=low[i]=ind++; inStack[i]=1; mstack.push(i); NODE *head=v[i]; while(head) { to=head->to; if(dfn[to]==-1) { tarjan(to); low[i]=min(low[i],low[to]); } else if(inStack[to]) { low[i]=min(low[i],dfn[to]); } head=head->next; } if(dfn[i]==low[i]) { do{ to=mstack.top(); inStack[to]=0; mstack.pop(); whichComponent[to]=componentNum; }while(i!=to); ++componentNum; } } void solve(void) { for(int i=1;i<=n;++i) if(dfn[i]==-1) tarjan(i); for(int i=1;i<=n;++i) { NODE *head=v[i]; while(head) { if(whichComponent[i]!=whichComponent[head->to]) ++dag_out[whichComponent[i]]; head=head->next; } } int flag=1; for (int i=1;i<=n;++i) if (!dag_out[whichComponent[i]]) { if(flag) flag=0; else printf(" "); printf("%d",i); } printf("\n"); } int main(void) { #ifdef DEBUG freopen("data.txt","r",stdin); #endif while(scanf("%d",&n)&&n) { init(); scanf("%d",&e); input(); solve(); } return 0; }