Loading

P3183 [HAOI2016]食物链(记忆化搜索 DAG)

P3183 [HAOI2016]食物链

题意

给出一张 n 个点 m 条边的有向无环的食物网,问这其中有多少条极长的食物链。

“注意单独的一种孤立生物不算一条食物链。”

思路

​ 这题可以用拓扑排序,也可以用记忆化搜索写。我们从每条食物链的顶点开始向下搜索,遇到一个叶子结点就可以形成一条食物链。数组 \(f_i\) 记录的是 从 i 为顶点的食物链条数,那我们就记忆化搜索一下,累加到顶点,最后把所有顶点的值加起来就可以了。

实现

#include <bits/stdc++.h>

using namespace std;
const int N = 100005;

int n, m;
int has_father[N]; //也可以用出入度来判断是否为食物链的顶点或者叶子结点。
int f[N];
vector<int> g[N];

int dfs(int u)
{
    if(f[u])    return f[u];
    int res = 0;
    bool is_leaf = true;
    for(int v : g[u])
    {
        is_leaf = false;
        res += dfs(v);
    }   
    if(is_leaf)
        return (has_father[u] == 1);
    f[u] = res;
    return res;
}

int main()
{
    cin >> n >> m;
    if(m == 0)
    {
        cout << 0 << '\n';
        return 0;
    }
    while(m --)
    {
        int x, y;
        cin >> x >> y;
        g[x].push_back(y);
        has_father[y] = 1;
    }

    int res = 0;
    for(int i = 1; i <= n; i ++)
        if(!has_father[i]) //无父节点,是某条食物链的起点。
            res += dfs(i);
    cout << res << '\n';
}
posted @ 2022-12-28 13:16  DM11  阅读(42)  评论(0编辑  收藏  举报