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';
}