栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【拓扑排序】P7077 [CSP-S2020] 函数调用

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【拓扑排序】P7077 [CSP-S2020] 函数调用

题意

有 n n n个元素,进行一些函数的操作。
功能可分为三类:

  1. 单点加;
  2. 全局乘;
  3. 依次执行若干次函数调用,保证不会出现递归(即不会直接或间接地调用本身)。
思路

考虑给这些函数的调用关系建图,得到一个DAG。

若无操作1,则用拓扑排序计算出每个函数调用后给全局乘上的值。

考虑算上操作1,那么对于一个加法后的乘法,会给加法的贡献也乘上一个权值,那么可以倒着进行一次拓扑排序,算出每个加法被乘上之后的贡献。

代码
#include 
#include 
#include 
#define int long long

const int mod = 998244353;

std::vector G1[100001], G2[100001];
int n, m;
int a[100001], mul[100001], cnt[100001], pos[100001], add[100001], deg[100001];

void topsort1() {
	std::queue q;
	for (int i = 0; i <= m; i++) {
		deg[i] = G2[i].size();
		if (!deg[i])
			q.push(i);
	}
	while (q.size()) {
		int x = q.front();
		q.pop();
		for (int i = 0; i != G1[x].size(); i++) {
			int y = G1[x][i];
			(mul[y] *= mul[x]) %= mod;
			deg[y]--;
			if (!deg[y])
				q.push(y);
		}
	}
}

void topsort2() {
	std::queue q;
	for (int i = 0; i <= m; i++) {
		deg[i] = G1[i].size();
		if (!deg[i])
			q.push(i);
	}
	while (q.size()) {
		int x = q.front();
		q.pop();
		int now = 1;
		for (int i = G2[x].size() - 1; i >= 0; i--) {
			int y = G2[x][i];
			(cnt[y] += now * cnt[x] % mod) %= mod;//具体地,通过计算每个函数操作次数来算贡献
			(now *= mul[y]) %= mod;
			deg[y]--;
			if (!deg[y])
				q.push(y);
		}
	}
}

signed main() {
	scanf("%lld", &n);
	for (int i = 1; i <= n; i++)
		scanf("%lld", &a[i]);
	scanf("%lld", &m);
	mul[0] = 1;
	for (int i = 1; i <= m; i++) {
		mul[i] = 1;
		int typ;
		scanf("%lld", &typ);
		if (typ == 1) {
			scanf("%lld %lld", &pos[i], &add[i]);
		} else if (typ == 2) {
			scanf("%lld", &mul[i]);
		} else {
			int len;
			scanf("%lld", &len);
			for (int j = 1, x; j <= len; j++) {
				scanf("%lld", &x);
				G1[x].push_back(i);
				G2[i].push_back(x);
			}
		}
	}
	int Q;
	scanf("%lld", &Q);
	for (int i = 1, x; i <= Q; i++) {
		scanf("%lld", &x);
		G1[x].push_back(0);
		G2[0].push_back(x);
	}
	cnt[0] = 1;
	topsort1();
	topsort2();
	for (int i = 1; i <= n; i++)
		(a[i] *= mul[0]) %= mod;
	for (int i = 1; i <= m; i++)
		(a[pos[i]] += cnt[i] * add[i] % mod) %= mod;
	for (int i = 1; i <= n; i++)
		printf("%lld ", a[i]);
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/511669.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号