思路:
尽量一步一步的走,若一步无法得出结果,在p1堆顶和第二堆顶的位置cost总和小于p2最大的cost时,选择p2堆顶的值。
题解:
#E2. Weights Division (hard version)
#wrtier: qiurun
#time: 2020/8/21
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define se second
#define fi first
int t,n;
typedef long long ll;
ll sum = 0,S;
const int N = 1e5+5;
vector<pair<int,pair<int,int> > > g[N];
struct pp{
ll w;
ll cnt;
ll cost;
pp(ll _w,ll _cnt):w(_w),cnt(_cnt){
cost = (w - w / 2) *cnt;
}
bool operator<(const pp& x)const{
return cost < x.cost;
}
};
priority_queue<pp> q1,q2;
ll dfs(int x,int pre){
ll s = 0;
if(x != 1 && g[x].size() == 1){
return 1;
}
for(int i = 0;i<g[x].size();i++){
pair<int,pair<int,int> > p = g[x][i];
int v = p.fi,w = p.se.fi,c = p.se.se;
if(v == pre)
continue;
ll ts = dfs(v,x);
sum += (ll)w * ts;
if(c == 1)
q1.push(pp(w,ts));
else
q2.push(pp(w,ts));
s += ts;
}
return s;
}
int main(){
int t;
scanf("%d",&t);
for(int i = 1;i <= t;i++){
sum = 0;
while(!q1.empty())q1.pop();
while(!q2.empty())q2.pop();
scanf("%d%lld",&n,&S);
for(int j = 1;j <= n;j++)
g[j].clear();
for(int j = 1;j <= n-1;j++){
int u,v,w,c;
scanf("%d%d%d%d",&u,&v,&w,&c);
g[u].pb(mp(v,mp(w,c)));
g[v].pb(mp(u,mp(w,c)));
}
dfs(1,-1);
ll cst = 0;
int flag = 0;
while(sum>S){
if (flag)break;
if(q1.empty()){
cst += 2;
pp x = q2.top();
q2.pop();
sum -= x.cost;
q2.push(pp(x.w/2,x.cnt));
}else if(q2.empty()){
cst ++;
pp x = q1.top();
q1.pop();
sum -= x.cost;
q1.push(pp(x.w/2,x.cnt));
}
else if(sum - q1.top().cost <= S){
cst ++;
sum = sum - q1.top().cost;
flag = 1;
break;
}else if(sum - q2.top().cost <= S){
cst+=2;
sum = sum - q2.top().cost;
flag =1;
break;
}else{
pp x1 = q1.top(), x2(x1.w/2,x1.cnt);
q1.pop();
bool flag = 1;
if(!q1.empty() && q1.top().cost > x2.cost){
//在这里wa了很多发,因为没有计算第一个折半后和第二个的cost谁比较大
x2 = q1.top();
q1.pop();
}else{
flag = 0;
x2= pp(x1.w/2,x1.cnt);
}
if(x1.cost + x2.cost >= q2.top().cost){
cst += 1;
sum = sum - x1.cost;
q1.push(pp(x1.w/2,x1.cnt));
if(flag)q1.push(x2);
}else{
q1.push(x1);
if(flag)q1.push(x2);
cst += 2;
pp x = q2.top();
q2.pop();
sum -= x.cost;
q2.push(pp(x.w/2,x.cnt));
}
}
}
printf("%lld\n",cst);
}
return 0;
}