题意 : 一个有向图 , 如果一个点u能够达到点v, v也能到达u, 则u是sink点 ; 找出所有的sink ,按顺序输入 ;
注意 如果点u能够到达的所有点中,有一个点不能到达u , u就不算是sink ,必须所有的点都能够达到u ;
第二组数据 : 1 --> 2
1 能到达的点事 1 , 2
但2不能到达1 , 所以1不是sink
2能够到达的点 是 2 ;
且2也能够到达2 ; 所有2是sink ;
分析 : 求一遍 强连通分量 , 显然 , 在一个强连通分量的所有点 ,都是sink , 并且这个强连通分量是出度为0 的 ;
#include<cstdio> #include<cstring> #include<map> #include<vector> #include<cmath> #include<cstdlib> #include<queue> #include <iomanip> #include<iostream> #include<algorithm> using namespace std ; const int N=5555 ; const int M=5000000; struct node { int u,v,next; }edge[M]; int head[N],dfn[N],low[N],vist[N],belong[N],out[N],stack[N],ans[N]; int top ,sum,cnt,dep; void add(int u ,int v ) { edge[top].u=u; edge[top].v=v; edge[top].next=head[u]; head[u]=top++; } void tarjan(int u) { low[u]=dfn[u]=++dep ; stack[cnt++]=u; vist[u]=1; for(int i = head[u] ; i!=-1 ; i=edge[i].next) { int v =edge[i].v ; if(!dfn[v]) { tarjan(v); low[u] = min( low[u] , low[v] ) ; }else if(vist[v]) low[u] = min( low[u] , dfn[v]) ; } if(dfn[u] == low[u]) { int x ; sum++; do { x = stack[--cnt]; vist[x]=0; belong[x]=sum; }while(x!=u); } } int main() { int n,m ,u,v; while(~scanf("%d",&n)) { if(n==0) break; scanf("%d",&m) ; top = cnt = sum = dep =0 ; memset(head,-1,sizeof(head)); for(int i = 1 ; i <= m ; i++) { scanf("%d%d",&u,&v); add(u,v) ; } memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)) ; memset(vist,0,sizeof(vist)); memset(belong,0,sizeof(belong)) ; memset(out,0,sizeof(out)) ; for(int i = 1 ; i <= n ; i++) if(!dfn[i]) tarjan(i) ; // printf("%d ",sum); for(int i = 1 ; i <= n ; i++) for(int j = head[i] ; j!=-1 ; j=edge[j].next) { int v = edge[j].v ; if(belong[i] != belong[v]) { out[belong[i]]++ ; } } int k = 0 ; for(int i = 1 ; i <= n ; i++) { if( out[belong[i]] == 0) { ans[k++]=i ; } } printf("%d",ans[0]) ; for(int i = 1 ; i < k ; i++) printf(" %d",ans[i]); puts("") ; } return 0 ; }