CSL的训练计划(拓扑排序)

本文介绍了一种利用拓扑排序解决特定问题的算法实现,该算法通过确定入度为0的节点开始,逐步推导出其他节点的值,最终求得满足条件的最大整数k。文中提供了一段完整的C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://ac.nowcoder.com/acm/contest/551/G

题解

题目保证了不会有环。
一开始唯一能确定的一个点便是入度为0的点,确定了一个点自然而然可以推出其他点。
a 1 + r 1 ∗ k + ( ( a 1 + r 1 ∗ k ) + r 2 ∗ k ) ) + ( ( ( a 1 + r 1 ∗ k ) + r 2 ∗ k ) ) + r 3 ∗ k ) + . . . = s u m a_1+r_1*k+( (a_1+r_1*k)+r_2*k))+(( (a_1+r_1*k)+r_2*k))+r_3*k)+... = sum a1+r1k+((a1+r1k)+r2k))+(((a1+r1k)+r2k))+r3k)+...=sum
k提出来后可以变成k*totval <= tot,k=tot/val
t o t v a l = ∑ 1 n v a l i + r i totval=\sum_{1}^{n} val_i+r_i totval=1nvali+ri

拓扑排序一遍求出val即可。

代码

#include <bits/stdc++.h>
using namespace std;
#define FOR0(a,b) for(int i = a; i < b; ++i)
#define FORE(a,b) for(int i = a; i <= b; ++i)
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 2e5+5;
int ind[maxn],n,m;
ll s,k, val[maxn];
vector<pii> G[maxn];

void add(int u, int v,int w) {
	G[u].push_back(make_pair(w,v));
}
int vis[maxn];
void solve() {
	queue<int> que;
	for(int i = 1; i <= n; ++i) 
		if(ind[i] == 0) que.push(i);

	int cnt = 0;
	while(!que.empty()) {
		int u = que.front();
		que.pop();
		cnt++;
		for(int i = 0; i < G[u].size(); ++i) {
			int r = G[u][i].first;
			int v = G[u][i].second;		
			val[v] = max(val[v],val[u]+r);
			ind[v]--;
			if(ind[v] == 0) que.push(v);
		}
	}


		ll sum = 0;
		for(int i = 1; i <= n; ++i) sum += val[i];
		//cout << sum << endl;
		if(sum > s) {
			puts("0");
			return;
		}
		if(sum == 0) cout << -1 << endl;
		else cout << (s/sum) << endl;
	
}
int main() {
	scanf("%d%d%lld", &n, &m, &s);
	int u, v, w;
	for(int i = 0; i < m; ++i) {
		scanf("%d%d%d", &u, &v, &w);
		add(u,v,w); ind[v]++;
	}
	solve();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值