P4017 最大食物链计数
题目描述
给你一个食物网,你要求出这个食物网中最大食物链的数量。
(这里的“最大食物链”,指的是生物学意义上的食物链,即最左端是不会捕食其他生物的生产者,最右端是不会被其他生物捕食的消费者。)
Delia 非常急,所以你只有 1 秒的时间。
由于这个结果可能过大,你只需要输出总数模上 80112002 的结果。
输入格式
第一行,两个正整数 n、m,表示生物种类 n 和吃与被吃的关系数 m。
接下来 m 行,每行两个正整数,表示被吃的生物A和吃A的生物B。
输出格式
一行一个整数,为最大食物链数量模上 80112002 的结果。
输入输出样例
输入
5 7
1 2
1 3
2 3
3 5
2 5
4 5
3 4
输出
5
说明/提示
各测试点满足以下约定:
代码
无注释版
#include<bits/stdc++.h>
using namespace std;
#define int long long
int r[5005],c[5005],f[5005];
const int mod=80112002;
queue<int> q;
vector<int> t[5005];
signed main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int n,m;cin>>n>>m;while(m--){int a,b;cin>>a>>b;r[b]++;c[a]++;t[a].push_back(b);}for(int i=1;i<=n;i++){if(!r[i]){f[i]=1;q.push(i);}}while(!q.empty()){int k=q.front();q.pop();int len=t[k].size();for(int i=0;i<len;i++){int next=t[k][i];r[next]--;f[next]=(f[next]+f[k])%mod;if(r[next]==0) q.push(t[k][i]);}}int ans=0;for(int i=1;i<=n;i++){if(!c[i]){ans=(ans+f[i])%mod;}}cout<<ans<<"\n";
}
有注释版
#include<bits/stdc++.h> // 引入所有标准库,方便使用各种容器和算法
using namespace std; // 使用标准命名空间#define int long long // 定义int为long long,避免溢出// 定义数组r[], c[], f[],分别表示每个节点的入度,出度和最大食物链的数量
int r[5005], c[5005], f[5005];
const int mod = 80112002; // 模数80112002queue<int> q; // 队列,用于存储当前没有捕食者的节点
vector<int> t[5005]; // 用于存储图,t[i]表示食物链中以i为节点的所有捕食者signed main() {ios::sync_with_stdio(false); // 关闭同步,提升输入输出效率cin.tie(0); // 解除cin与cout的同步cout.tie(0); // 解除cin与cout的同步int n, m; // n为生物种类数量,m为捕食关系的数量cin >> n >> m; // 输入n和m// 处理m条捕食关系while (m--) {int a, b; // a为被吃的生物,b为吃a的生物cin >> a >> b; // 输入捕食关系r[b]++; // b的入度+1,表示b捕食了ac[a]++; // a的出度+1,表示a被捕食t[a].push_back(b); // 将b加入到a的捕食者列表}// 初始时,将没有捕食者的生物(即入度为0的节点)加入队列for (int i = 1; i <= n; i++) {if (!r[i]) {f[i] = 1; // 没有捕食者的生物可以独立形成一个食物链q.push(i); // 将该生物加入队列}}// 通过拓扑排序的方式,计算每个生物能形成的最大食物链数量while (!q.empty()) {int k = q.front(); // 取出队列头部的元素kq.pop(); // 移除队列头部的元素int len = t[k].size(); // 获取k的捕食者数量for (int i = 0; i < len; i++) = 0; i < len; i++) { // 遍历每个捕食k的生物int next = t[k][i]; // next是捕食k的生物r[next]--; // next的入度减1,表示已处理完k// 将k的食物链数量加入到next的食物链数量中,注意模运算f[next] = (f[next] + f[k]) % mod;// 如果next的入度变为0,表示它已处理完所有捕食对象,可以加入队列if (r[next] == 0) {q.push(next);}}}int ans = 0; // 用来存储最终的结果// 计算没有捕食者(即出度为0)的生物形成的食物链的数量for (int i = 1; i <= n; i++) {if (!c[i]) { // 如果i没有捕食其他生物(出度为0)ans = (ans + f[i]) % mod; // 将i的食物链数量累加到结果中}}cout << ans << "\n"; // 输出结果
}