P4017 最大食物链计数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目可进入链接查看,这里不再赘述。(ps:我明明找的是dp啊,怎么开始复习拓扑了呢)
思路:
题意是找出完全食物链(从生产者到最高消费者)的个数。一开始看错了,算的是最长食物链。
由题意可知,我们这道题的数据是有一定的顺序的。但是输入未必符合顺序。所以要用到拓扑排序,从生产者开始,到最高消费者。
//这道题的题意是找出完全食物链(从生产者到最高级消费者)的个数
#include<iostream>
#include<queue>
#define maxn 500050
using namespace std;
const int mod = 80112002;
int n, m;
int eat[maxn],in[maxn],dp[maxn];
int head[maxn], ed[maxn], nex[maxn], idx=0;//链式前向星四件套
queue<int>q;
void add(int a, int b)
{
ed[idx] = b;
nex[idx] = head[a];
head[a] = idx++;
}
void top()//拓扑排序
{
for (int i = 1; i <= n; i++)
if (in[i] == 0)
{
q.push(i);//生产者为起点
dp[i] = 1;//链上至少一个生产者
}
while (!q.empty())
{
int p = q.front();
q.pop();
for (int i = head[p]; i!=-1; i = nex[i])
{
int e = ed[i];
dp[e] = (dp[e] + dp[p])%mod;//在清除点的时候,顺便把删除点的权值加上
in[e]--;
if (in[e] == 0)
q.push(e);
}
}
}
int res;
int main()
{
scanf("%d %d", &n, &m);
memset(head, -1, sizeof(head));
for (int i = 1; i <= m; i++)
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
in[b]++;//入度+1,入读为0的为生产者
eat[a]++;//所有被吃的+1,为0的是食物链顶端的男人
}
top();
for (int i = 1; i <= n; i++)
if (eat[i] == 0)//食物链顶端的男人
res = (res+dp[i])%mod;
printf("%d", res);
}