首页 > 其他分享 >P4017 最大食物链计数

P4017 最大食物链计数

时间:2023-07-31 19:12:34浏览次数:47  
标签:食物链 head 计数 int 入度 ++ tail include P4017

P4017 最大食物链计数

初中生物都忘了,食物链不知道从生产者还是消费者开始了

题目给出有向无环图,从入度为零的点(不保证唯一)开始,走到出度为零的点(不保证唯一)共有多少条路径,答案对80112002取模

保证

道路单向无重边(A吃B就没有B吃A,也不会自己吃自己

图中无环 (不会有A吃B,B吃C,C吃A)

思路

一眼是dfs,但是时间复杂度 $ O(MN^2) $ 数据卡的太死了,只有20%

那么想快一点的方法:

用数组 \(lenth[i]\) 表示从任意一个入度为零的点到i点的链长度
对于任意一个入度为零的点\(x\),\(f[x]\)初始化为1
对于任意入度非零的点y,\(f[y]\) 等于任意能到达\(y\)点的\(u\)点的\(f[u]\)之和

因此需要计算保证任意点链长时,所有可达该点的节点链长已经被计算

所以我们需要拓扑排序,找到一个合适的计算顺序保证上述条件

  • “最左端是不会捕食其它生物的生产者,最右端是不会被其他生物捕食的消费者”

并且(A,B)表示“被吃的生物A和吃A的生物B”

建图开个vector,存单向边应该从A到B (不是捕食关系,而是被捕食关系,初中生物全忘了

  • 起点和终点不唯一,可能有多个起点和终点,入队的时候要都进去,计算总和的时候要计算所有出度为零的点的链长和

  • 数据可能很大,计算过程中随时模mod,否则有可能爆

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;

const int mod = 80112002, N = 5009;
int n, m, A, B, out[N], in[N], lenth[N], ans;
vector<int> v[N];

struct queue{  // 手写队列 
	int head = 0, tail = 0, que[N + 10];
	void push(int x) {que[tail ++] = x;}
	void pop() {head ++;}
	int front() {return que[head];}
	int size() {return tail - head;}
	bool empty() {return head >= tail;}
	void clear() {head = tail = 0;}
}q;

int main() {
//	freopen("P4017_1.in", "r", stdin);
	scanf("%d%d", &n, &m);
	while (m --) {
		cin >> A >> B;
		v[A].push_back(B);  // 建A向B的单向边 
		out[A] ++;          // A的出度 ++ 
		in[B] ++;			// B的入度 ++ 
	}
	for (int i = 1; i <= n; i ++)
		if (!in[i]) {  // 循环找所有可能起点 
			q.push(i); // 入队 
			lenth[i] = 1;  // 链长为1 
		}
	while (!q.empty()) {  // 拓扑排序 
		int head = q.front();
		q.pop();
		for (int i = 0; i < v[head].size(); i ++) {
			int p = v[head][i];
			in[p] --;  // 相连的点入度 -- 
			lenth[p] = (lenth[p] + lenth[head]) % mod;  // 计算链长 
			if (in[p] == 0) q.push(p);  // 将入度为零的点入队 
		}
	}
	for (int i = 1; i <= n; i ++)
		if(!out[i]) ans = (ans + lenth[i]) % mod;  // 随时模 
		// 统计所有可能的终点的链长和 
	printf("%d", ans % mod);
	return 0;
}

标签:食物链,head,计数,int,入度,++,tail,include,P4017
From: https://www.cnblogs.com/plokmnjiu/p/17594244.html

相关文章

  • 计数题选做
    [ABC267G]IncreasingKTimesDifficulty:*2561。题目所求即为重排\(a\),使得满足\(a_i<a_{i+1}\)的下标\(i\)恰有\(k\)个的方案数。容易发现,\(a\)的顺序其实没有影响,可以直接先将\(a\)排序。设\(dp_{i,j}\)表示前\(i\)个数,恰有\(j\)个下标满足\(a_k<a_{k+1}......
  • java统计数据库字段
    packagedb;importjava.sql.*;importjava.util.ArrayList;importjava.util.List;/***@Author:dominic**/publicclassStatistic{publicstaticvoidmain(String[]args)throwsSQLException,ClassNotFoundException{Stringa="x......
  • 2.1.1 进位计数制
    最古老的计数方法十进制计数法进位计数制:有0~9,共十种符号。逢十进一推广:r进制计数法二进制←→八进制、十六进制各种进制的常见书写方式十进制→任意进制真值和机器数知识回顾注意:有的十进制小数无法用二进制精确表示。如:0.3......
  • sql server 存储过程 计数
    SQLServer存储过程计数的实现介绍在SQLServer中,存储过程是一种可重复使用的数据库对象,可以接受参数并返回结果。存储过程可以包含一系列的SQL语句,用于完成特定的数据库操作。在本文中,我们将讨论如何编写一个存储过程来实现计数功能。流程下面是实现SQLServer存储过程......
  • 计数dp
    错位排列计数(组合意义dp)题目给定长度为\(n\)的排列,求解其错位排列数题解设\(D_n\)表示长度为\(n\)的排列的错排数,考虑我们已经知道了前\(n-1\)个错排数,那么对新加入的这第\(n\)个数进行分类讨论直接与前面的数交换,有\((n-1)\timesD_{n-2}\)种方案放在前......
  • 计数题目合集
    CF1342F题目链接很巧妙的一个计数题。原题目等价于构建一个递增序列\(p\),赋予每个数字一个属性\(b\),满足\(b_{p_i}=p_i\),其余任选。且\(\forallj,\sum\limits_{i=1}^n[b_i=p_j]a_i<\sum\limits_{i=1}^n[b_i=p_{j+1}]a_i\)。最大化递增序列\(p\)的长度。先考虑一个朴......
  • 【模板】图的计数相关:行列式及求值、Matrix-Tree 定理、BEST 定理、LGV 引理
    归类为线性代数、图论。证明都是神仙,特别是名字带“理”的,不证了。行列式定义行列式(Determinant)是对\(n\)阶方阵\(A\)定义的,是一个标量。\(A\)的\(n\)阶行列式\(det(A)\)或\(|A|\)定义如下:\[det(A)=\sum_p(-1)^{\mu(p)}\prod_{i}A[i][p_i].\]这里将排列的逆序对数......
  • abc090d <枚举计数>
    题目D-RemainderReminder代码Code//https://atcoder.jp/contests/abc090/tasks/arc091_b#include<iostream>#include<algorithm>#include<vector>#include<cstring>usingnamespacestd;usingLL=longlong;usingPII=pair<in......
  • Luogu 5296 生成树计数
    好像有道题是求生成树权值和的和的,考虑\(\sum\limits_{T}\sum\limits_{e\inE(T)}w_e\)咋做。每条边给一个边权\(v_e(x)=1+w_ex\),然后跑矩阵树:\[\text{ans}=[x]\sum\limits_{T}\prod\limits_{e\inE(T)}v_e(x)\]受到来自神秘力量的启示,我们考虑类似上面这样构造边权。考虑......
  • Burnside定理和Polya计数
    置换群Burnside定理和Polya计数都需要运用置换群的知识置换群主要有三种运算,分别是合成运算、恒等置换、置换的逆运用着三种运算就可以推导出Burnside定理和Polya计数的公式Burnside定理Burnside定理的主要应用是循环排列计数、项链计数、正五角形着色等下面给出一道例题P......