【洛谷 P4017】最大食物链计数 题解(深度优先搜索+动态规划+邻接表+记忆化搜索+剪枝)

最大食物链计数

题目背景

你知道食物链吗?Delia 生物考试的时候,数食物链条数的题目全都错了,因为她总是重复数了几条或漏掉了几条。于是她来就来求助你,然而你也不会啊!写一个程序来帮帮她吧。

题目描述

给你一个食物网,你要求出这个食物网中最大食物链的数量。

(这里的“最大食物链”,指的是生物学意义上的食物链,即最左端是不会捕食其他生物的生产者,最右端是不会被其他生物捕食的消费者。)

Delia 非常急,所以你只有 1 1 1 秒的时间。

由于这个结果可能过大,你只需要输出总数模上 80112002 80112002 80112002 的结果。

输入格式

第一行,两个正整数 n 、 m n、m nm,表示生物种类 n n n 和吃与被吃的关系数 m m m

接下来 m m m 行,每行两个正整数,表示被吃的生物A和吃A的生物B。

输出格式

一行一个整数,为最大食物链数量模上 80112002 80112002 80112002 的结果。

样例 #1

样例输入 #1

5 7
1 2
1 3
2 3
3 5
2 5
4 5
3 4

样例输出 #1

5

提示

各测试点满足以下约定:

【补充说明】

数据中不会出现环,满足生物学的要求。(感谢 @AKEE )


思路

食物网可以看作是一个有向图,每个生物种类是一个节点,每个食物关系是一个有向边。所求的最大食物链的数量,就是计算有向图中从源点(没有入度的点)到达终点(没有出度的点)的所有路径的数量。

首先,定义一些全局变量。其中,N 是节点的最大数量,MOD 是取模的基数,nm 分别表示节点的数量和边的数量,ans 用来存储最终的结果,dp 是一个数组,用来存储每个节点的最大食物链的数量,inDoutD 是两个数组,分别用来存储每个节点的入度和出度,g 是一个邻接表,用来存储图的信息,vis 是一个位集,用来标记每个节点是否被访问过。

main 函数中,首先通过 memset 函数将 inDoutDdp 数组的所有元素初始化为 0,然后读取节点的数量 n 和边的数量 m,并根据输入的边的信息,更新 inDoutDg。之后,对于每一个没有入度的节点,调用 dfs 函数进行深度优先搜索,并更新 ans

dfs 函数中,首先检查当前节点是否被访问过,如果已经被访问过,就直接返回。然后,将当前节点标记为已访问。接着,如果当前节点没有出度,就将 dp 数组中对应的元素设置为 1,然后返回。否则,对于当前节点的每一个邻接节点,调用 dfs 函数,并更新 dp 数组中对应的元素。

最后,输出 ansMOD 取模的结果。

注意

由于结果可能过大,每次计算路径数求和时都需要输出总数模上 80112002 80112002 80112002 的结果,否则无法通过部分测试点。


AC代码

#include <algorithm>
#include <bitset>
#include <cstring>
#include <iostream>
#include <vector>
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;const int N = 1e6 + 7;
const int INF = 0x3f3f3f3f;
const int MOD = 80112002;ll n, m;
ll ans = 0;
ll dp[N];
ll inD[N], outD[N];
vector<ll> g[N];
bitset<N> vis;void dfs(ll x) {if (vis[x]) {return;}vis[x] = 1;// cout << x << endl;if (!outD[x]) {// 最右端是不会被其他生物捕食的消费者dp[x] = 1;return;}ll sum = 0;for (const auto i : g[x]) {dfs(i);sum += dp[i];sum %= MOD;}dp[x] = max(dp[x], sum);
}int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);memset(inD, 0, sizeof(inD));memset(outD, 0, sizeof(outD));memset(dp, 0, sizeof(dp));cin >> n >> m;for (int i = 1; i <= m; i++) {ll a, b;cin >> a >> b;outD[a]++;inD[b]++;g[a].push_back(b);}vis.reset();for (int i = 1; i <= n; i++) {if (!inD[i]) {// 最左端是不会捕食其他生物的生产者dfs(i);ans += dp[i];ans %= MOD;// cout << i << " " << dp[i] << endl;}}//	for(int i = 1; i <= n; i++) {//		cout << i << " " << dp[i] << endl;//	}cout << (ans % MOD) << "\n";return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/610788.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uname -a --输出和系统本身相关-内核版本、硬件架构32位/64位

uname命令&#xff1a;主要用于输出一组操作系统的信息 包含内核的版本、硬件架构是32位还是64位 输入--help后看看效果&#xff0c;一目了然 首先输出完整信息&#xff1a; 我们再依次来输出一下&#xff1a; 最后&#xff0c;我们只需要记住uname命令可以输出和系统本身相关…

Python数据结构与算法——算法(贪心算法、动态规划

贪心算法 介绍&#xff1a;贪心算法又称贪婪算法&#xff0c;是指在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;它所做出的是在某种意义上的局部最优解。 贪心算法并不保证会得到最优解&#xff0c;但…

LangChain-18 Caching 将回答内容进行缓存 可在内存中或数据库中持久化缓存

背景描述 可以将问答的内容缓存起来&#xff0c;如果是相同的问题&#xff0c;那么将会直接把答案返回去&#xff0c;可以节约费用和计算。 安装依赖 pip install -qU langchain-core langchain-openai编写代码 我们可以通过 InMemoryCache 进行内存缓存 或者 SQLiteCache …

电脑无法开机?原因分析与解决方案

电脑无法开机是一种常见的问题&#xff0c;可能会给用户带来诸多困扰。无法启动可能是由于硬件故障、软件问题或者其他未知原因引起的。在本文中&#xff0c;我们将介绍三种常见的方法来解决电脑无法开机的问题&#xff0c;以帮助用户尽快恢复正常使用。 方法1&#xff1a;检查…

spfa算法(java代码)

题目: 851. spfa求最短路 - AcWing题库 输入样例: 3 3 1 2 5 2 3 -3 1 3 4 输出样例: 2 分析&#xff1a; 先去定义一个class 类似于c里面的pair 里面有两个变量x, y 因为后面需要用优先队列来处理最短路问题需要指出比较x还是y 因此我们让这个pair类实现 Comparable 接口 实…

HarmonyOS实战开发-WebSocket的使用。

介绍 本示例展示了WebSocket的使用&#xff0c;包括客户端与服务端的连接和断开以及客户端数据的接收和发送。 WebSocket连接&#xff1a;使用WebSocket建立服务器与客户端的双向连接&#xff0c;需要先通过createWebSocket方法创建WebSocket对象&#xff0c;然后通过connect…

数据应用OneID:ID-Mapping Spark GraphX实现

前言 说明 以用户实体为例&#xff0c;ID 类型包含 user_id 和 device_id。当然还有其他类型id。不同id可以获取到的阶段、生命周期均不相同。 device_id 生命周期通常指的是一个设备从首次被识别到不再活跃的整个时间段。 user_id是用户登录之后系统分配的唯一标识&#xff…

Ubuntu (Linux系统) 下载安装 Qt 环境

在官网http://download.qt.io/archive/qt/ 下载安装包&#xff0c;默认linux平台下提供的安装包以run后缀结尾 也可以选择其它地址下载 Qt官网下载地址&#xff1a;https://download.qt.io&#xff1b; 国内镜像下载地址&#xff1a;https://mirrors.cloud.tencent.com/qt/ 。建…

【牛客SQL快速入门】SQL基础(三)

一、条件函数 IF 条件函数 IF函数是最常用到的条件函数&#xff0c;写法为 if(xn,a,b)&#xff0c;xn代表判断条件&#xff0c;如果xn时&#xff0c;那么结果返回a&#xff0c;否则返回b。 -- 把非北京大学的用户统一归为其他大学 Select device_id,if(university ‘北京大…

nginx反向代理conf

打开nginx配置。 对登录功能测试完毕后&#xff0c;接下来&#xff0c;我们思考一个问题&#xff1a;前端发送的请求&#xff0c;是如何请求到后端服务的&#xff1f; 前端请求地址&#xff1a;http://localhost/api/employee/login 后端接口地址&#xff1a;http://localho…

Java中队列

队列是一种常见的数据结构&#xff0c;它按照先进先出&#xff08;FIFO&#xff09;的原则管理元素。在 Java 中&#xff0c;队列通常是通过链表或数组实现的&#xff0c;不同的实现类在内部数据结构和操作上可能有所不同。 1.原理 1.数据结构&#xff1a;队列的基本数据结构…

【网站项目】学生选课系统小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…