题目:E1. Weights Division (easy version)
题意读错了折磨的,给定一棵树,n个点n-1条边,每一条边有权重,给定一个价值S,问
,意思即根到每个叶子节点的距离路线的总和价值小于S,你每次可以操作任意一条边使其变成
,
问最小多少次操作使其小于S。
根节点到每个叶子节点的路线都要计算一遍,那我们可以先统计某一个节点的叶子节点个数,也就是这条路线要被走多少次,总价值就是
,然后意思是任意选择一条边向下取整,我们可以大根堆的优先队列来解决。
直接放入价值推w[i]会掉精度,是向下取整。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PP;
const int mod=1e9+7;
ll n,s,sum;
ll times[100010];
vector<PP>hh[100100];
struct cmp {
bool operator()(PP t1,PP t2) {
return ((t1.first-t1.first/2)*t1.second) < ((t2.first-t2.first/2)*t2.second);
}
};
priority_queue<PP,vector<PP>,cmp>que;
void dfs(int u,int f) {
if(hh[u].size()==1&&u!=1) {
times[u]=1;
return ;
}
for(int i=0;i<hh[u].size();i++) {
int v=hh[u][i].first;
if(v==f)
continue;
dfs(v,u);
times[u]+=times[v];
}
return ;
}
void ddffss(int u,int f) {
if(hh[u].size()==1&&u!=1) {
return ;
}
for(int i=0;i<hh[u].size();i++) {
int v=hh[u][i].first;
if(v==f)
continue;
que.push(make_pair(hh[u][i].second,times[v]));
sum+=hh[u][i].second*times[v];
ddffss(v,u);
}
return ;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld %lld",&n,&s);
sum=0;
while(!que.empty())
que.pop();
for (int i=0;i<=n+1;i++)
hh[i].clear(),times[i]=0;
for(int i=1;i<n;i++) {
ll u,v,val;
scanf("%lld %lld %lld",&u,&v,&val);
hh[u].push_back(make_pair(v,val));
hh[v].push_back(make_pair(u,val));
}
dfs(1,-1);
ddffss(1,-1);
if(sum<=s) {
printf("0\n");
continue;
}
ll ans=0;
while(sum>s) {
PP temp;
temp=que.top();
que.pop();
ans++;
sum-=(temp.first-temp.first/2)*temp.second;
que.push(make_pair(temp.first/2,temp.second));
}
printf("%lld\n",ans);
}
return 0;
}
题目:E2. Weights Division (hard version)
题意同上,就是每条边加入了需要耗费的次数,有耗费1或者2,问最小的耗费数,那么问题就是选择耗费1的边还是2,就有了贪心的策略,两个优先队列分别存,对情况进行分析判定。可见代码,写的比较繁杂,注意细节。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PP;
const int mod=1e9+7;
ll n,s,sum;
struct A {
ll edgeto,edgeval,cost;
};
ll times[100010];
vector<A>hh[100100];
struct cmp {
bool operator()(PP t1,PP t2) {
return ((t1.first-t1.first/2)*t1.second) < ((t2.first-t2.first/2)*t2.second);
}
};
priority_queue<PP,vector<PP>,cmp>q1,q2;
void dfs(int u,int f) {
if(hh[u].size()==1&&u!=1) {
times[u]=1;
return ;
}
for(int i=0;i<hh[u].size();i++) {
int v=hh[u][i].edgeto;
if(v==f)
continue;
dfs(v,u);
times[u]+=times[v];
}
return ;
}
void ddffss(int u,int f) {
if(hh[u].size()==1&&u!=1) {
return ;
}
for(int i=0;i<hh[u].size();i++) {
int v=hh[u][i].edgeto;
if(v==f)
continue;
if(hh[u][i].cost==1) {
q1.push(make_pair(hh[u][i].edgeval,times[v]));
}
else {
q2.push(make_pair(hh[u][i].edgeval,times[v]));
}
sum+=hh[u][i].edgeval*times[v];
ddffss(v,u);
}
return ;
}
ll solve(ll x,ll y) {
return ((x-x/2)*y);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld %lld",&n,&s);
sum=0;
while(!q1.empty())
q1.pop();
while(!q2.empty())
q2.pop();
for (int i=0;i<=n+1;i++)
hh[i].clear(),times[i]=0;
for(int i=1;i<n;i++) {
ll u,v,uu,vv;
scanf("%lld %lld %lld %lld",&u,&v,&uu,&vv);
A temp;
temp.edgeto=v,temp.edgeval=uu,temp.cost=vv;
hh[u].push_back(temp);
temp.edgeto=u;
hh[v].push_back(temp);
}
dfs(1,-1);
ddffss(1,-1);
if(sum<=s) {
printf("0\n");
continue;
}
ll ans=0;
while(sum>s) {
PP q1temp,q2temp;
if(q1.size()==0) {
ans+=2;
q2temp=q2.top();
q2.pop();
sum-=solve(q2temp.first,q2temp.second);
q2.push(make_pair(q2temp.first/2,q2temp.second));
continue;
}
q1temp=q1.top();
ll t1=solve(q1temp.first,q1temp.second);
if(sum-t1<=s) {
ans++;
break;
}
if(q2.size()==0) {
ans++;
sum-=t1;
q1.pop();
q1.push(make_pair(q1temp.first/2,q1temp.second));
continue;
}
q2temp=q2.top();
ll t2=solve(q2temp.first,q2temp.second);
if(q1.size()==1) {
t1+=solve(q1temp.first/2,q1temp.second);
if(t1<t2) {
ans+=2;
sum-=t2;
q2.pop();
q2.push(make_pair(q2temp.first/2,q2temp.second));
}
else {
ans++;
sum-=solve(q1temp.first,q1temp.second);;
q1.pop();
q1.push(make_pair(q1temp.first/2,q1temp.second));
}
continue;
}
ll t3=solve(q1temp.first/2,q1temp.second);
q1.pop();
ll t5=solve(q1.top().first,q1.top().second);
if((t2>=t1+t3)&&(t2>=t1+t5)) {
ans+=2;
sum-=t2;
q2.pop();
q1.push(q1temp);
q2.push(make_pair(q2temp.first/2,q2temp.second));
}
else {
ans++;
sum-=t1;
q1.push(make_pair(q1temp.first/2,q1temp.second));
}
}
printf("%lld\n",ans);
}
return 0;
}