Codeforces 730 C Bulmart [bfs+贪心]

本文介绍了一种使用BFS算法解决特定问题的方法:在给定的城市和商店网络中,寻找从某城市出发购买指定数量鞋子且总价不超过预算的最短路径。通过维护一个多元素集来动态调整最优解。

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

题意:给你n个城市,m个商店,商店有k只价格为p的鞋子,一共q个询问,每次询问从某个城市出发,得到r只鞋子并且总价小于等于a的最小距离为多少(最小距离是购买鞋子的城市中,距离最大的城市要最小)

题解:bfs询问的城市,用set维护当前搜索过的点中的最优解(按照price从大到小排序),假如当前城市商店中的鞋子数+已有的鞋子数>需要的鞋子数的时候,我们从set中删除价格大的多余的鞋子,假如满足条件直接返回答案。

注意:set和multiset = =!! 这个地方错了太多次了

AC代码:

#include<stdio.h>
#include<vector>
#include<queue>
#include<string.h>
#include<algorithm>
#include<set>
#define N 5005
using namespace std;
typedef long long ll;
ll n,m;
struct node
{
	ll num,price;
	node(){}
	node(ll num,ll price)
	{
		this->num=num;
		this->price=price;
	}
};
struct haha
{
	ll u,step;
	haha(){}
	haha(ll u,ll step)
	{
		this->u=u;
		this->step=step;
	}
};
vector<ll>vt[N];
vector<node>shop[N];
multiset<node>st;
multiset<node>::iterator it;
bool operator<(node a,node b)
{
	if(a.price==b.price)return a.num>b.num;
	return a.price>b.price;
}
ll mark[N];
ll bfs(ll pos,ll need,ll money)
{
	st.clear();
	memset(mark,0,sizeof(mark));
	queue<haha>que;
	que.push(haha(pos,0));
	mark[pos]=1;
	ll nownum=0,nowprice=0;
	while(!que.empty())
	{
		haha k=que.front();
		que.pop();
		for(ll i=0;i<shop[k.u].size();i++)
		{
			st.insert(shop[k.u][i]);
			nownum+=shop[k.u][i].num;
			nowprice+=shop[k.u][i].num*shop[k.u][i].price;
			while(nownum>need)
			{
				it=st.begin();
				ll dif=min(it->num,nownum-need);
				node a=*st.begin();
				st.erase(st.begin());
				a.num-=dif;
				if(a.num>0) st.insert(a);
				nownum-=dif;
				nowprice-=dif*a.price;
			}
		}
		if(nownum==need&&nowprice<=money)return k.step;
		for(ll i=0;i<vt[k.u].size();i++)
		{
			ll to=vt[k.u][i];
			if(mark[to])continue;
			mark[to]=1;
			que.push(haha(to,k.step+1));
		}
	}
	return -1;
}
int main()
{
	scanf("%lld%lld",&n,&m);
	for(ll i=0;i<m;i++)
	{
		ll u,v;
		scanf("%lld%lld",&u,&v);
		vt[u].push_back(v);
		vt[v].push_back(u);
	}
	ll s;
	scanf("%lld",&s);
	for(ll i=0;i<s;i++)
	{
		ll pos,num,price;
		scanf("%lld%lld%lld",&pos,&num,&price);
		shop[pos].push_back(node(num,price));
	}
	ll q;
	scanf("%lld",&q);
	while(q--)
	{
		ll pos,need,money;
		scanf("%lld%lld%lld",&pos,&need,&money);
		printf("%lld\n",bfs(pos,need,money));
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值