题意:给你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));
}
}