🍄前言
大家好,我是一勺黑猫。今天是每日一题的第二十六天,欢迎更多小伙伴加入到我们的打卡计划中,希望和你们在学习算法的路上一起进步~
(偷懒了几天,现在就算是半划水状态吧,大三事情好多 哭泣)
🙎作者简介:一个正在努力学算法和后端的大三girl
⏳每日一题打卡地:高校算法学习社区
🎈联系方式:157543570(qq)
💨往期内容:
黑猫的每日一题
https://blog.csdn.net/xingziyy/category_11731303.html
🍄今日题目
P4017 最大食物链计数 - 洛谷 | 计算机科学教育新生态
🌰思路:现学了一下拓扑序,总结起来就是:需要一个ru数组,一个chu数组,分别记录每个顶点的入度数和出度数。一个dp数组记录到每个顶点为止的所有路径数。然后用bfs遍历所有入度为0的点,每遍历到它的一个后继节点,就将后继节点的入度数减1。如果该后继节点的入度数减为0了,就将它入队。然后更新每个后继节点的dp值,将其加上其前驱结点的dp值。最后从起点(入度为0)到终点(出度为0)的路径总数就是所有终点的dp值之和(起点和终点都可能有多个)
🌰AC代码:
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define MOD 80112002
int ru[5010],chu[5010]; //记录每个顶点的入度数和出度数
int dp[5010]; //记录每个顶点所拥有的食物链条数
vector<int> v[5010];
queue<int> q;
int n,m;
void toposort(){
for(int i=1;i<=n;i++){
if(!ru[i]){ //入度为0代表生产者,把所有生产者入队
q.push(i);
dp[i]=1; //每个生产者都能确定一条食物链
}
}
while(!q.empty()){
int first=q.front();
q.pop();
for(int i=0;i<v[first].size();i++){
int ans=v[first][i];
if(--ru[ans]==0) //当前节点的所有前驱节点都遍历完,就把它入队
q.push(ans);
dp[ans]=(dp[ans]+dp[first])%MOD;
}
}
}
int main(){
scanf("%d%d",&n,&m);
int a,b;
while(m--){
scanf("%d%d",&a,&b);
chu[a]++;
ru[b]++;
v[a].push_back(b);
}
toposort();
int res=0;
for(int i=1;i<=n;i++){
if(!chu[i]) //总共的最大食物链数就是所有最终消费者拥有的食物链数之和
res=(res+dp[i])%MOD;
}
printf("%d",res);
return 0;
}