缩点+拓扑
/************************************************************** Problem: 1051 User: lxy8584099 Language: C++ Result: Accepted Time:304 ms Memory:14872 kb ****************************************************************/ // by pig~~ #include<cstdio> #include<bitset> #include<queue> using namespace std; const int N=1e4+5,M=5e4+5; bitset <N> a[N]; struct pp{int from,to,nxt;}e[M],f[M]; int n,m,head[N],dfn[N],low[N],sta[N],top,tot,fa[N],h[N],d[N],size[N],num,ans,dd[N]; bool vis[N]; queue < int > q; void add(int u,int v){e[++tot].nxt=head[u];e[tot].from=u;e[tot].to=v;head[u]=tot;} int min(int a,int b){return a>b?b:a;} void dfs(int u) { dfn[u]=low[u]=++tot;vis[u]=1;sta[++top]=u; for(int j=head[u];j;j=e[j].nxt) { int v=e[j].to; if(!dfn[v]) { dfs(v);low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { num++;int v; do{v=sta[top--];vis[v]=0;size[u]++;fa[v]=u;}while(u!=v); } } void work() { for(int i=1;i<=n;i++) if(!d[i]&&fa[i]==i) { q.push(i);vis[i]=1; } while(!q.empty()) { int u=q.front();q.pop(); for(int j=h[u];j;j=f[j].nxt) { int v=f[j].to;a[v]|=a[u];dd[v]++; if(!vis[v]&&dd[v]==d[v]) { vis[v]=1;q.push(v); } } } } int main() { // freopen("popular.in","r",stdin); // freopen("popular.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) fa[i]=i,a[i][i]=1; for(int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),add(u,v);tot=0; for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i);tot=0; // printf("num:%d\n",num); for(int i=1,u,v;i<=m;i++) { u=fa[e[i].from],v=fa[e[i].to]; if(u!=v) { f[++tot].nxt=h[u];f[tot].to=v;h[u]=tot;d[v]++; } } work(); for(int i=1;i<=n;i++) { int xx=a[i].count(); // printf("%d\n",xx); if(xx==num) { // printf("dsajdaskl\n"); ans+=size[i]; } } printf("%d\n",ans); return 0; } /* 6 6 1 2 2 3 3 4 4 5 5 1 5 6 */