思路

记忆化搜索、拓扑排序的题目。
对于一个已经走过一次的点,后面能走的情况都是确定的,
只要能把情况数记录下来,后面的结点就不需要再走一遍了,
就可以很大程度上节省时间。

代码

#include <bits/stdc++.h>

using namespace std;

const int maxm=200005,maxn=100005;

struct E{
    int next, to;
}edge[maxm];

int head[maxn], cnt, ans;
int n,m,a,b,ru[maxn],chu[maxn],f[maxn];

void addedge(int a,int b){
    edge[++cnt].next=head[a];
    edge[cnt].to=b;
    head[a]=cnt;
}

int dfs(int now){
    if(f[now]) return f[now]; //记忆化 
    if(!chu[now]) return 1;
    int res=0;
    for(int i=head[now];i;i=edge[i].next){
        res+=dfs(edge[i].to);
    }
    f[now]=res;
    return res;
}

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    cin>>n>>m;
    memset(ru, 0, sizeof(ru));
    memset(chu, 0, sizeof(chu));
    for(int i=1;i<=m;i++){
        cin>>a>>b;
        addedge(a,b);
        ru[b]++,chu[a]++;
    }
    for(int i=1;i<=n;i++){
        if(!ru[i]&&chu[i]) ans+=dfs(i);
    }
    cout<<ans;
    return 0;
}