bzoj4562
直接记忆化搜(不记忆化不知道行不行)注意判断单独一个点。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <vector> using namespace std; const int maxn=100000+10; const int maxm=200000+10; struct hh { int v,next; }e[maxm]; int n,m,point,ans; int head[maxn],rd[maxn],cd[maxn],vis[maxn],mem[maxn]; template <class T> void read(T&x) { x=0;char c=getchar();int f=0; while(c<'0'||c>'9'){f|=(c=='-');c=getchar();} while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^=48),c=getchar(); x=f?-x:x; } void add(int u,int v) { e[++point].v=v;e[point].next=head[u];head[u]=point; rd[v]++;cd[u]++; } int dfs(int x) { if(!cd[x]) { if(!rd[x])return 0; return 1; } if(mem[x])return mem[x]; for(int i=head[x];i!=-1;i=e[i].next) { int v=e[i].v; if(vis[v])continue; vis[v]=1; int k=dfs(v); mem[x]+=k; vis[v]=0; } return mem[x]; } int main() { memset(head,-1,sizeof(head)); read(n);read(m); int u,v; for(register int i=1;i<=m;i++) { read(u);read(v); add(u,v); } for(int i=1;i<=n;i++) { if(!rd[i])ans+=dfs(i); } printf("%d",ans); return 0; }