题目
现在给你 nn 个物种和 mm 条能量流动关系,求其中的食物链条数。
物种的名称为从 11 到 nn 的编号。
mm 条能量流动关系形如
a_1a1 b_1b1
a_2a2 b_2b2
a_3a3 b_3b3
… …
a_mam b_mbm
其中 a_i \ b_iai bi 表示能量从物种 a_iai 流向物种 b_ibi。注意单独的一种孤立生物不算一条食物链。
输入
第一行两个整数 nn 和 mm,接下来 mm 行每行两个整数 a_i \ b_iai bi 描述 mm 条能量流动关系。
(保证输入数据符合生物学特点,且不会有重复的能量流动关系出现)
[tips:应该是指没有环,也没有重边]
输出
一个整数,即食物网中的食物链条数。
思路
到达每个消费者的食物链数量等于到达它的食物的食物链的数量的和,因此可以用动态规划,从生产者开始,一直递推到顶级消费者,再取和。
#include<stdio.h>
#include<iostream>
#include<vector>
#include<string.h>
using namespace std;
int n, m;
int in[100005];
int out[100005];
vector<vector<int>> graph = vector<vector<int>>(100005, vector<int>());
int dp[100005];
int search(int num)
{
int ans = 0;
if(dp[num] != -1) ans = dp[num];
else if(out[num] == 0) ans = 1; //出度为0,顶级消费者
else
{
for(int i = 0; i < out[num]; i++) ans += search(graph[num][i]);
}
dp[num] = ans;
return ans;
}
int main()
{
scanf("%d %d", &n, &m);
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
memset(dp, -1, sizeof(dp));
int a, b;
while(m--)
{
scanf("%d %d", &a, &b);
graph[a].push_back(b);
out[a]++, in[b]++;
}
int sum = 0;
for(int i = 1; i <= n; i++)
{
if(in[i] == 0 && out[i] != 0) sum += search(i);
}
printf("%d", sum);
return 0;
}