P4017 最大食物链计数

1|0P4017 最大食物链计数

1|1记忆化搜索 DP 角度解

  • 从捕食者向被捕食者建边
  • 维护每个生物的捕食 eat,和被捕食数量 beat
  • 对每一个食物链顶端 dfs,向下搜索直到找到最低级的生物,记忆化当前结点对应的食物链长度。
#include <iostream> #include <algorithm> #include <cstring> #define mod %80112002 using namespace std; const int N = 5e3 + 5; const int M = 5e5 + 5; struct Node{ int to, next; }edge[M]; int head[N]; int cnt = 0; int n, m; int ans; int eat[N], beat[N], F[N]; void addEdge(int a, int b) { edge[cnt].to = b; edge[cnt].next = head[a]; head[a] = cnt++; } void preProcessing() { memset(head, -1 , sizeof(head)); cin >> n >> m; for (int i = 1; i <= m; i++) { int a, b; cin >> a >> b; addEdge(b, a); eat[b]++; beat[a]++; } } int dfs(int u) { int sum = 0; if (!eat[u]) { return 1; } if (F[u]) { return F[u]; } for (int j = head[u]; j != -1; j = edge[j].next) { sum = (sum + dfs(edge[j].to)) mod; } return F[u] = sum; } int main() { preProcessing(); for (int i = 1; i <= n; i++) { if (!beat[i]) { ans += dfs(i); ans = ans mod; } } cout << ans; return 0; }

1|2拓扑排序角度解

  • 从被捕食者向捕食者建边
  • 维护每个生物(结点)的入度 ind,和出度 otd
  • 直接对整个食物网拓扑排序,排序的过程中自然维护一个 num 数组表示到当前结点的最长链。
  • 求和出度为 0num 数组即可。
#include <iostream> #include <algorithm> #include <cstring> #include <queue> #define mod %80112002 using namespace std; const int N = 5e3 + 5; const int M = 5e5 + 5; struct Node{ int to, next; }edge[M]; int head[N]; int cnt = 0; int n, m; int ans; int ind[N], otd[N], F[N], num[N]; void addEdge(int a, int b) { edge[cnt].to = b; edge[cnt].next = head[a]; head[a] = cnt++; } void preProcessing() { memset(head, -1 , sizeof(head)); cin >> n >> m; for (int i = 1; i <= m; i++) { int a, b; cin >> a >> b; addEdge(a, b); ind[b]++; otd[a]++; } } void bfs() { queue<int> q; for (int i = 1; i <= n; i++) { if (!ind[i]) num[i] = 1, q.push(i); } while(!q.empty()) { int f = q.front(); q.pop(); for (int i = head[f]; i != -1; i = edge[i].next) { int t = edge[i].to; --ind[t]; num[t] = (num[t] + num[f]) mod; if (ind[t] == 0) q.push(t); } } } int main() { preProcessing(); bfs(); for (int i = 1; i <= n; i++) { if (!otd[i]) { ans = (ans + num[i]) mod; ans = ans mod; } } cout << ans; return 0; }

__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/17864768.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示