NC54148 货物收集 二分答案+基础bfs

链接:https://ac.nowcoder.com/acm/problem/54148
来源:牛客网

题目描述
Venn想要收集一些货物。

Venn有一颗n个节点的树,一开始Venn在1号节点,其他每个节点都有一定的货物储备,Venn只要经过那些节点,就可以收集到节点的所有货物。每个节点的货物只能收集一次。

显然,Venn并不能轻易的收集所有的货物。每一条连接着两个节点的路径,都有一个邪恶的怪物镇守。Venn的武力值必须不小于怪物的武力值才能安全地从这条路径上通过。

Venn一开始的武力值是0,但是她可以选择健身来提升自己的武力值。每健身一分钟,就会提升一点武力值。Venn并不想收集所有的货物,只要最终收集到的货物总量不低于W就可以了。Venn一旦开始收集,就不能再健身了。但是Venn的速度很快,可以认为收集货物和从路径上经过都不需要时间。

由于Venn还急着去颓废,所以她想让你帮她计算收集到指定数量的货物最少需要几分钟。

点击下载大样例
输入描述:

一行两个正整数n,W。

接下来一行,有n-1个正整数,第i个数字aia_iai​表示编号为i+1节点的货物储备。

接下来n-1行,每行有三个正整数u,v,w,表示有一条路径链接编号为u,v的节点,并且路径上有一个武力值为w的怪物。

输出描述:

一行一个整数,表示最小时间花费。

示例1
输入
复制

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

输出
复制

5

备注:

对于30%30%30%的数据,n≤10n\leq10n≤10

对于60%60%60%的数据,n≤2000n\leq2000n≤2000,保证数据随机生成。

对于另外20%20%20%的数据,整棵树是一条链。

对于100%100%100%的数据,n≤106,1≤u,v≤n,1≤w,ai,W≤109n\leq10^6,1\leq u,v\leq n,1\leq w,a_i,W \leq 10^9n≤106,1≤u,v≤n,1≤w,ai​,W≤109,保证所有点货物储备之和不小于W.


题意 : 给定一棵树,有边权,有点权,开始在1点,
走到一个点可以获得权值w[i],人的能力值W大于边权 W U V W_{UV} WUV时可以从u走到v
求能拿到至少M点权和,人的能力值最小是多少

  • 二分答案,判断能不能拿到大于m的点权和

#ifdef debug
#include <time.h>
#include "win_majiao.h"
#endif

#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <math.h>

#define MAXN ((int)1e6+7)
#define ll long long int
#define INF (0x7f7f7f7f)
#define fori(lef, rig) for(int i=lef; i<=rig; i++)
#define forj(lef, rig) for(int j=lef; j<=rig; j++)
#define fork(lef, rig) for(int k=lef; k<=rig; k++)
#define QAQ (0)

using namespace std;
typedef vector<vector<int> > VVI;

#define show(x...) \
	do { \
		cout << "[" << #x << " -> "; \
		err(x); \
	} while (0)

void err() { cout << "]" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cout << a << ' '; err(x...); }

namespace FastIO{

	char print_f[105];
	void read() {}
	void print() { putchar('\n'); }

	template <typename T, typename... T2>
	   inline void read(T &x, T2 &... oth) {
		   x = 0;
		   char ch = getchar();
		   ll f = 1;
		   while (!isdigit(ch)) {
			   if (ch == '-') f *= -1; 
			   ch = getchar();
		   }
		   while (isdigit(ch)) {
			   x = x * 10 + ch - 48;
			   ch = getchar();
		   }
		   x *= f;
		   read(oth...);
	   }
	template <typename T, typename... T2>
	   inline void print(T x, T2... oth) {
		   ll p3=-1;
		   if(x<0) putchar('-'), x=-x;
		   do{
				print_f[++p3] = x%10 + 48;
		   } while(x/=10);
		   while(p3>=0) putchar(print_f[p3--]);
		   putchar(' ');
		   print(oth...);
	   }
} // namespace FastIO
using FastIO::print;
using FastIO::read;

int n, m, Q, K, w[MAXN];

struct Edge {
	int v, w;
} ;
vector<Edge> G[MAXN]; 

bool vis[MAXN];
ll bfs(ll mid) {
	queue<int> q;
	memset(vis, 0, sizeof(vis));
	q.push(1); vis[1] = true;
	ll sum = 0;
	while(!q.empty()) {
		auto u = q.front(); q.pop();
		for(auto ed : G[u]) {
			if(vis[ed.v]) continue ;
			if(ed.w <= mid) {
				q.push(ed.v);
				sum += w[ed.v];
				vis[ed.v] = true;
			}
		}
	}
	return sum;
}

signed main() {
#ifdef debug
	freopen("test.txt", "r", stdin);
	clock_t stime = clock();
#endif
	read(n, m);
	for(int i=2; i<=n; i++) read(w[i]);
	int u, v, p;
	for(int i=2; i<=n; i++) {
		read(u, v, p);
		G[u].push_back({v, p}), G[v].push_back({u, p});
	}
	ll lef = 0, rig = 1E9+7, mid, ans = m;
	while(lef <= rig) {
		mid = (lef + rig) >> 1;
		ll tmax = bfs(mid);
		// show(mid);
		if(tmax >= m) { ans = mid; rig = mid - 1; }
		else lef = mid + 1;
	}
	printf("%lld\n", ans);




#ifdef debug
	clock_t etime = clock();
	printf("rum time: %lf 秒\n",(double) (etime-stime)/CLOCKS_PER_SEC);
#endif 
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值