强连通分量tarjan算法+缩点。。。
需要注意的一点就是当给定的图本身就是个强连通图时直接输出0即可。。。
#include<iostream> #include<string.h> #include<algorithm> #include<string> #define N 20005 #define M 500005 using namespace std; bool istack[N]; int dfn[N],low[N],in[N],out[N],belong[N],stack[N],head[N]; typedef struct str { int to; int next; }Node; Node node[M]; int res,num,top,index,n,m; void init() { memset(istack,false,sizeof(istack)); memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(stack,0,sizeof(stack)); memset(belong,0,sizeof(belong)); res=num=top=0; index=1; } void dfs(int i) { dfn[i]=low[i]=index++; istack[i]=true; stack[top++]=i; for(int j=head[i];j!=-1;j=node[j].next) { int v=node[j].to; if(!dfn[v]) { dfs(v); low[i]=min(low[i],low[v]); } else if(istack[v]) low[i]=min(low[i],dfn[v]); } int u; if(dfn[i]==low[i]) { res++; do { u=stack[--top]; istack[u]=false; belong[u]=res; }while(u!=i); } } void tarjan() { for(int i=1;i<=n;++i) if(!dfn[i]) dfs(i); } void solve() { if(res==1) {cout<<"0"<<endl;return;} 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]]++; in[belong[node[j].to]]++; } int p=0,q=0; for(int i=1;i<=res;++i) { if(!out[i]) p++; if(!in[i]) q++; } cout<<max(p,q)<<endl; } int main() { while(cin>>n>>m) { init(); for(int i=0;i!=m;++i) { int a,b; cin>>a>>b; node[num].to=a; node[num].next=head[b]; head[b]=num++; } tarjan(); solve(); }return 0; }