思路:
缩点,计算入度为0点的个数即可;
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int N=1e5+10; struct asd{ int to; int next; }; asd q[N*4]; int head[N*4],tol; int n,m; int dfn[N]; int low[N]; int stap[N]; int in[N]; int vis[N]; int tp,p,cnt; int kc[N],kr[N]; void add(int a,int b) { q[tol].to=b; q[tol].next=head[a]; head[a]=tol++; } void tarjan(int u) { dfn[u]=low[u]=++tp; stap[++p]=u; vis[u]=1; for(int v=head[u];v!=-1;v=q[v].next) { int i=q[v].to; if(!dfn[i]) { tarjan(i); low[u]=min(low[u],low[i]); } else if(vis[i]) low[u]=min(low[u],dfn[i]); } if(dfn[u]==low[u]) { cnt++; int temp; while(1) { temp=stap[p]; vis[temp]=0; in[temp]=cnt; p--; if(temp==u) break; } } } int fun() { memset(kc,0,sizeof(kc)); for(int i=1;i<=n;i++) { for(int v=head[i];v!=-1;v=q[v].next) { int to=q[v].to; if(in[to]!=in[i]) { kc[in[to]]++; } } } int ans=0; for(int i=1;i<=cnt;i++) { if(!kc[i]) ans++; } return ans; } int main() { int T,cas=1,x,y; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); tol=0; memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(vis,0,sizeof(vis)); while(m--) { scanf("%d%d",&x,&y); add(x,y); } tp=p=cnt=0; for(int i=1;i<=n;i++) { if(!dfn[i]) tarjan(i); } printf("Case %d: %d ",cas++,fun()); } return 0; }