codefoces730C Bulmart 二分答案+贪心check && 堆维护

来源:互联网 发布:淘宝秒杀抢拍器手机版 编辑:程序博客网 时间:2024/06/03 07:44

C. 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 city gj 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 44 25 41 23 224 1 23 2 361 2 62 3 73 1 24 3 85 2 56 1 10
output
2-1223-1
题解:这道题目我们想了两种解法:

第一种,也是比较好写的算法,就是把所有的商店按照商品价格从小到大排序。并对于每个询问,从起点开始跑一遍bfs,得到每个商店的距离。

再二分答案,在check函数里这么写,依据价格从小到大遍历商店,贪心的选取合适数量的商品。如果最后能取到r个商品并且剩余的钱数>=0,说明本次check是可行的。

这个算法非常好想,也好写。

第二种,这种算法不太好想,也不太好写。

我们需要r个商品,那么我们可以从g点bfs的过程中,维护一个可以容纳商品数量为r的堆,每次bfs到一个新的地点的时候,我们都把这个地点所有的商店里的商品跟堆顶商品进行比较,然后更新这个堆。(这个堆维护的是到目前为止,价格前r小的r个商品)

这样的话,每到一个点,我们都判断一下当前堆中的商品价格总和是否小于等于我们带的现金a,如果是那么就可以直接输出答案了。答案即是当前这个点到起点的距离。

代码1,二分版本:

#include <bits/stdc++.h>using namespace std;#define int long longconst int MAXN = 1e5;const int INF = 1e5;int head[MAXN];int dis[MAXN];int vis[MAXN];int cnt;struct edge{     int v;     int next;     int cost; }Es[MAXN<<1];  void init(){     cnt = 0;     memset(head,-1,sizeof(head)); }inline void add_edge(int i,int j,int cost){       Es[cnt].v = j;     Es[cnt].cost = cost;     Es[cnt].next = head[i];     head[i] = cnt++; }   struct shop{int id,num,price;friend bool operator<(shop sp1,shop sp2){return sp1.price < sp2.price;}};int n,m,q,snum;vector<shop> shops;bool check(int x,int knum,int cash){for(int i = 0;i < shops.size();++i){shop sp = shops[i];if(dis[sp.id] > x) continue;int k = min(knum,sp.num);knum -= k;cash -= k * sp.price;if(!knum) break;}if(!knum && cash >= 0) return true;return false;}void bfs(int s){memset(vis,0,sizeof(vis));memset(dis,0x3f,sizeof(dis));queue<int> Q;dis[s] = 0;vis[s] = 1;Q.push(s);while(!Q.empty()){int u = Q.front();Q.pop();for(int e = head[u];e != -1;e = Es[e].next){int v = Es[e].v; if(!vis[v]){dis[v] = dis[u] + 1;vis[v] = 1;Q.push(v);}}}}main(){init();scanf("%lld%lld",&n,&m);for(int i = 1;i <= m;++i){int a,b;scanf("%lld%lld",&a,&b);add_edge(a,b,1);add_edge(b,a,1);}scanf("%lld",&snum);for(int i = 0;i < snum;i++){int id,price,num;scanf("%lld%lld%lld",&id,&num,&price);shops.push_back((shop){id,num,price});}sort(shops.begin(),shops.end());scanf("%lld",&q);while(q--){int src,knum,cash;scanf("%lld%lld%lld",&src,&knum,&cash);bfs(src);int sl = 0,sr = INF;while(sr - sl > 1){int mid  = (sl + sr) >> 1;if(check(mid,knum,cash)) sr = mid;else sl = mid;}if(check(sl,knum,cash)) printf("%lld\n",sl);else if(check(sr,knum,cash)) printf("%lld\n",sr);else printf("%lld\n",-1LL);}return 0;}

代码2,维护小顶堆版:

#include <bits/stdc++.h>using namespace std;#define int long longtypedef pair<int,int> pii;const int MAXN = 5005;int head[MAXN],vis[MAXN];int dis[MAXN];int cnt;struct edge{     int v;     int next;     int cost; }Es[10007];  struct node{int dis,val,num;friend bool operator<(node n1,node n2){// choose the maxreturn n1.val < n2.val;}};priority_queue<node> heap;vector<pii> shops[MAXN];void init(){     cnt = 0;     memset(head,-1,sizeof(head)); }inline void add_edge(int i,int j,int cost){       Es[cnt].v = j;     Es[cnt].cost = cost;     Es[cnt].next = head[i];     head[i] = cnt++; }   int bfs(int s,int items,int cash){memset(dis,0,sizeof(dis));memset(vis,0,sizeof(vis));queue<int> Q;Q.push(s);dis[s] = 0;vis[s] = 1;int heap_num = 0;int heap_cost = 0;while(!Q.empty()){int u = Q.front();Q.pop();for(int i = 0;i < shops[u].size();i++){pii p = shops[u][i];int tmp_price = p.first;int tmp_num = p.second;int f = 1;while(f && tmp_num){f = 0;int remain = items - heap_num;if(remain > 0){heap.push((node){dis[u],tmp_price,min(tmp_num,remain)});int kkk = min(tmp_num,remain);heap_num += kkk;heap_cost += kkk * tmp_price;tmp_num -= kkk;f = 1;}else if(remain == 0){node td = heap.top();while(tmp_num && td.val > tmp_price){heap.pop();f = 1;int kkk = min(td.num,tmp_num);heap_cost += kkk * (tmp_price - td.val);td.num -= kkk;tmp_num -= kkk;if(td.num) heap.push(td);heap.push((node){dis[u],tmp_price,kkk});td = heap.top();}}}}if(heap_num >= items && heap_cost <= cash){int ans = 0;while(!heap.empty()){node p = heap.top();heap.pop();if(p.num > 0){ans = max(ans,p.dis);}}return ans;}for(int e = head[u];e != -1;e = Es[e].next){int v = Es[e].v;if(vis[v]) continue;dis[v] = dis[u] + 1;vis[v] = 1;Q.push(v);}}return -1;}int n,m,q;main(){init();scanf("%lld%lld",&n,&m);for(int i = 1;i <= m;i++){int a,b;scanf("%lld%lld",&a,&b);add_edge(a,b,1);add_edge(b,a,1);}int shop = 0;scanf("%lld",&shop);for(int i = 1;i <= shop;i++){int ver;int num,cost;scanf("%lld%lld%lld",&ver,&num,&cost);shops[ver].push_back(make_pair(cost,num));}for(int i = 1;i <= n;i++) sort(shops[i].begin(),shops[i].end());scanf("%lld",&q);while(q--){int g,r,a;scanf("%lld%lld%lld",&g,&r,&a);while(!heap.empty()){heap.pop();}cout<<bfs(g,r,a)<<endl;}return 0;}





原创粉丝点击