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

这篇具有很好参考价值的文章主要介绍了【洛谷 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

提示

各测试点满足以下约定:

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

【补充说明】

数据中不会出现环,满足生物学的要求。(感谢 @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 的结果,否则无法通过部分测试点。文章来源地址https://www.toymoban.com/news/detail-852389.html


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;
}

到了这里,关于【洛谷 P4017】最大食物链计数 题解(深度优先搜索+动态规划+邻接表+记忆化搜索+剪枝)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 洛谷 P1387 最大正方形 题解

    通过二维前缀和判定矩形内是否全为1,计算和等于长度的平方就判断为是 复杂度 (Theta (n^2log{n})) 设状态 (f_{i,j}) 为以第 (i) 行 (j) 列为右下角的最大正方形的边长, (a_{i,j}) 表示输入矩阵中的数值,有转移方程: [f_{i,j} = (min(f_{i-1,j},f_{i,j-1},f_{i-1,j-1}) + 1) * a_{i,j}] 解释:

    2024年02月16日
    浏览(45)
  • 【洛谷 P1029】[NOIP2001 普及组] 最大公约数和最小公倍数问题 题解(更相减损术)

    输入两个正整数 x 0 , y 0 x_0, y_0 x 0 ​ , y 0 ​ ,求出满足下列条件的 P , Q P, Q P , Q 的个数: P , Q P,Q P , Q 是正整数。 要求 P , Q P, Q P , Q 以 x 0 x_0 x 0 ​ 为最大公约数,以 y 0 y_0 y 0 ​ 为最小公倍数。 试求:满足条件的所有可能的 P , Q P, Q P , Q 的个数。 一行两个正整数 x 0 , y 0

    2024年02月09日
    浏览(44)
  • 洛谷 P8742题解

    简单版(P2347)传送门 原题传送门 有一道 类似 的题目(P2347),先扯一扯~ 动态规划入门题(01背包 可行性问题 )~ 我们 设 (dp_j) 为能否用砝码称出 (j) 重量 ,1 为 可以 ,0 为 不可以 。 为了转移, (dp_{_{0}} gets 1) , 什么都不放时,重量为 0 ,因此可以称出。 那么 枚举

    2024年02月06日
    浏览(55)
  • 洛谷P1249题解

    一个正整数一般可以分为几个互不相同的自然数的和,如 3 = 1 + 2 3=1+2 3 = 1 + 2 , 4 = 1 + 3 4=1+3 4 = 1 + 3 , 5 = 1 + 4 = 2 + 3 5=1+4=2+3 5 = 1 + 4 = 2 + 3 , 6 = 1 + 5 = 2 + 4 6=1+5=2+4 6 = 1 + 5 = 2 + 4 。 现在你的任务是将指定的正整数 n n n 分解成若干个互不相同的自然数的和,且使这些自

    2024年02月05日
    浏览(52)
  • 洛谷 CF1743APassword 题解

    https://www.luogu.com.cn/problem/CF1743A 已知一个长度为四的,只包含字符 0 , 1 , 2 , … , 9 0,1,2,dots ,9 0 , 1 , 2 , … , 9 的字符串中不会出现哪些字符,求可能的字符串的数量。 Monocarp has forgotten the password to his mobile phone. The password consists of $ 4 $ digits from $ 0 $ to $ 9 $ (note that it can start wit

    2023年04月20日
    浏览(47)
  • 洛谷AT4888 题解-伦伦数

    A positive integer XX is said to be a lunlun number if and only if the following condition is satisfied: In the base ten representation of XX (without leading zeros), for every pair of two adjacent digits, the absolute difference of those digits is at most 11 . For example, 12341234 , 11 , and 334334 are lunlun numbers, while none of 3141531415 

    2024年02月06日
    浏览(52)
  • 2353. 设计食物评分系统;1895. 最大的幻方;842. 将数组拆分成斐波那契序列

    2353. 设计食物评分系统 核心思想:首先明确我们有哪些功能,首先是修改某种食物分数的功能,然后第二点是能够每次弹出分数高字典序小的食物名字。由这两个我们想到了a = 食物[分数],b = 烹饪方式[分数,食物名字] 然后有一点经验的感觉,就是使用堆,每次从堆中弹出最

    2024年02月14日
    浏览(72)
  • 洛谷 P1336 最佳课题选择 题解

    题目链接 状态:考虑 (f_{i,j}) 表示前 (i) 种论文里面,一共写了 (j) 篇,的最少花费时间。 转移策略:我们一次考虑每一种论文写多少篇。假设写 (k) 篇, (k in [0,j] cap mathbb{Z}) ,有转移方程: [f_{i,j} = min(f_{i-1,j-k} + text{cost}(i,k)), k in [0,j] cap mathbb{Z}] 其中 [text{

    2024年02月14日
    浏览(38)
  • 洛谷 U123017 机器人题解

    机器人会按照输入的指令进行移动,命令包括’E’,‘S’,‘W’,\\\'N’四种,分别对应东南西北。执行某个命令时它会消耗1秒钟向对应的方向移动一格单位。 在0时刻机器人位于(0,0)。 如果遇到’E’命令,向右一个单位,即到达(1,0)。如果遇到’S’命令,向下一个单位,即到达

    2024年03月21日
    浏览(43)
  • 【洛谷题解】B2010 带余除法

    题目链接:带余除法 - 洛谷 题目难度:入门 涉及知识点:除法,计算余数 题意: 分析:计算商后再用a/商*b得余数 AC代码: 总结:计算商后再用a/商*b得余数

    2024年02月19日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包