思路:tarjan()算法,记录每个点的出度值(缩点之后),把所以出度为0的点找出来,然后进行从小到大排序
#include<iostream> #include<algorithm> #include<cstdio> #include<string.h> #include<vector> #include<stack> #define maxn 5111 using namespace std; int V,E,sum,tem; int dfn[maxn],low[maxn],vis[maxn],outd[maxn],belong[maxn]; int ans[maxn]; vector<int>gra[maxn]; stack<int>S; int MIN(int a,int b) { return a>b?b:a; } void tarjan(int pox) { vis[pox]=2; dfn[pox]=low[pox]=++sum; S.push(pox); for(int i=0; i<gra[pox].size(); i++) { int t=gra[pox][i]; if(!dfn[t]) { tarjan(t); low[pox]=MIN(low[pox],low[t]); } else if(vis[t]==2) { low[pox]=MIN(low[pox],dfn[t]); } } if(dfn[pox]==low[pox]) { ++tem; while(!S.empty()) { int gh=S.top(); S.pop(); outd[gh]=0; belong[gh]=tem; vis[gh]=1; if(gh==pox) break; } } } int main() { int a,b; while(scanf("%d",&V),V) { tem=sum=0; memset(ans,0,sizeof(ans)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); memset(belong,0,sizeof(belong)); for(int i=0; i<maxn; i++) gra[i].clear(); while(!S.empty()) S.pop(); scanf("%d",&E); for(int i=0; i<E; i++) { scanf("%d%d",&a,&b); gra[a].push_back(b); } for(int i=1; i<=V; i++) if(!dfn[i]) tarjan(i); for(int i=1; i<=V; i++) for(int j=0; j<gra[i].size(); j++) { if(belong[i]!=belong[gra[i][j]]) { outd[belong[i]]++; } } int as=0; for(int i=1; i<=V; i++) if(!outd[belong[i]]) ans[as++]=i; if(as==0) { printf("\n"); continue; } sort(ans,ans+as); for(int i=0; i<as; i++) if(i==0) printf("%d",ans[i]); else printf(" %d",ans[i]); printf("\n"); } return 0; }