2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest c 二分+bfs

9 篇文章 0 订阅

Bulmart
time limit per test
1.5 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

A new trade empire is rising in Berland. Bulmart, an emerging trade giant, decided to dominate the market of ... shovels! And now almost every city in Berland has a Bulmart store, and some cities even have several of them! The only problem is, at the moment sales are ... let's say a little below estimates. Some people even say that shovels retail market is too small for such a big company to make a profit. But the company management believes in the future of that market and seeks new ways to increase income.

There are n cities in Berland connected with m bi-directional roads. All roads have equal lengths. It can happen that it is impossible to reach a city from another city using only roads. There is no road which connects a city to itself. Any pair of cities can be connected by at most one road.

There are w Bulmart stores in Berland. Each of them is described by three numbers:

  • ci — the number of city where the i-th store is located (a city can have no stores at all or have several of them),
  • ki — the number of shovels in the i-th store,
  • pi — the price of a single shovel in the i-th store (in burles).

The latest idea of the Bulmart management is to create a program which will help customers get shovels as fast as possible for affordable budget. Formally, the program has to find the minimum amount of time needed to deliver rj shovels to the customer in the citygj for the total cost of no more than aj burles. The delivery time between any two adjacent cities is equal to 1. If shovels are delivered from several cities, the delivery time is equal to the arrival time of the last package. The delivery itself is free of charge.

The program needs to find answers to q such queries. Each query has to be processed independently from others, i.e. a query does not change number of shovels in stores for the next queries.

Input

The first line contains two integers nm (1 ≤ n ≤ 50000 ≤ m ≤ min(5000, n·(n - 1) / 2)). Each of the next m lines contains two integers xe and ye, meaning that the e-th road connects cities xe and ye (1 ≤ xe, ye ≤ n).

The next line contains a single integer w (1 ≤ w ≤ 5000) — the total number of Bulmart stores in Berland. Each of the next w lines contains three integers describing the i-th store: ci, ki, pi (1 ≤ ci ≤ n, 1 ≤ ki, pi ≤ 2·105).

The next line contains a single integer q (1 ≤ q ≤ 1000) — the number of queries. Each of the next q lines contains three integers describing the j-th query: gj, rj and aj (1 ≤ gj ≤ n1 ≤ rj, aj ≤ 109)

Output

Output q lines. On the j-th line, print an answer for the j-th query — the minimum amount of time needed to deliver rj shovels to the customer in city gj spending no more than aj burles. Print -1 if there is no solution for the j-th query.

Example
input
6 4
4 2
5 4
1 2
3 2
2
4 1 2
3 2 3
6
1 2 6
2 3 7
3 1 2
4 3 8
5 2 5
6 1 10
output
2
-1
2
2
3
-1



题意:给出n个城市,m条边,w个商店,每个商店所属的城市,商品数量,商品单价,q个询问,每次询问给g城市送r个商品在总价不超过a的条件下最小时间,从一个城市到相邻城市所需时间为1。


题解:先按商品价格排序,对于每次询问先bfs出距离此城市的距离,然后二分时间即可。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<deque>
using namespace std;
typedef long long ll;
ll n,m,cnt,head[5005],shp,vis[5005],g,r,a;
deque<ll>sp;
struct node{
	ll to,nex;
}edge[10005];
struct node1{
	ll loc,num,pri;
}shop[5005];
void add(ll u,ll v){
	edge[cnt].to=v;
	edge[cnt].nex=head[u];
	head[u]=cnt++;
}
bool cmp(node1 a,node1 b){
	return a.pri<b.pri;
}
ll check(ll mid){
	ll ans=0,i,dd=r;
	for(i=1;i<=shp;i++){
		if(vis[shop[i].loc]<=mid){
			dd-=shop[i].num;
			ans+=shop[i].num*shop[i].pri;
		}
		if(dd<=0){
			ans-=shop[i].pri*(-dd);
			break;
		}
	}
	if(dd<=0){
		if(ans<=a)return 1;
	}
	return 0;
}
int main(){
	scanf("%lld%lld",&n,&m);
	memset(head,-1,sizeof(head));
	ll i,j,x,y,q;
	for(i=1;i<=m;i++){
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	scanf("%d",&shp);
	for(i=1;i<=shp;i++)scanf("%lld%lld%lld",&shop[i].loc,&shop[i].num,&shop[i].pri);
	sort(shop+1,shop+1+shp,cmp);
	scanf("%d",&q);
	while(q--){
		scanf("%lld%lld%lld",&g,&r,&a);
		for(i=1;i<=n;i++)vis[i]=5005;
		while(!sp.empty())sp.pop_front();
		sp.push_back(g);
		vis[g]=0;
		ll l=0,r=n;
		while(!sp.empty()){
			ll f=sp.front();
			sp.pop_front();
			for(i=head[f];~i;i=edge[i].nex){
				ll v=edge[i].to;
				if(vis[v]==5005){
					sp.push_back(v);
					vis[v]=vis[f]+1;
				}
			}
		}
		while(l+1<r){
			ll mid=(l+r)/2;
			if(check(mid))r=mid;
			else l=mid;
		}
		if(check(l))printf("%lld\n",l);
		else if(check(r))printf("%lld\n",r);
		else printf("-1\n");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值