第一道强连通分量题,tarjan算法+缩点,,输出出度为0的顶点。。。
//强连通分量为搜索树中的一颗子树 //stack自定义栈,dfn(u)为结点u的次序编号 //low(u)为u或u的子树能够追溯到的最早的栈中结点的次序号 //belong[u]为u所属连通分量 #include<iostream> #include<string.h> #include<algorithm> #include<string> #define N 5005 using namespace std; bool istack[N]; int stack[N],dfn[N],low[N],belong[N],head[N],out[N]; typedef struct str { int to; int next; }Node; Node node[N*3]; int top,num,res,index,n; void init() { memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(out,0,sizeof(out)); memset(istack,false,sizeof(istack)); num=top=res=0;index=1; } void dfs(int i) { dfn[i]=low[i]=index++; stack[top++]=i; istack[i]=true; for(int j=head[i];j!=-1;j=node[j].next) { int v=node[j].to; if(!dfn[v]) { dfs(v); if(low[v]<low[i]) low[i]=low[v]; } else if(istack[v]&&dfn[v]<low[i]) low[i]=dfn[v]; } int u; if(dfn[i]==low[i])//回溯,以i为根的搜索子树上的所有结点是一个强连通分量 { res++; do{ u=stack[--top]; istack[u]=false; belong[u]=res; }while(i!=u); } } void tarjan() { for(int i=1;i<=n;++i) if(!dfn[i]) dfs(i); } void solve()//缩点 { for(int i=1;i<=n;++i) { for(int j=head[i];j!=-1;j=node[j].next) if(belong[i]!=belong[node[j].to]) { out[belong[i]]++; break; } } for(int i=1;i<=n;++i) if(!out[belong[i]]) cout<<i<<" "; cout<<endl; } int main() { int m; while(cin>>n>>m&&n) { init(); for(int i=0;i!=m;++i) { int a,b; cin>>a>>b; node[num].to=b; node[num].next=head[a]; head[a]=num++; } tarjan(); solve(); }return 0; }