CF1399E1 Weights Division (easy version) (优先队列)

这种题目很容易就联想到独立算贡献,某条边的贡献就是他的权值和底下叶子节点的数量相关。

我们用优先队列的方法取最大,记得算大小的时候是按减一半的贡献再算

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> pll;
const int N=2e5+10;
const int M=2e6+10;
const int inf=0x3f3f3f3f;
const ll mod=998244353;
int h[N],ne[N],e[N];
ll w[N],idx;
struct node{
    ll a;
    int b;
    bool operator <(const node &t) const{
        return a<t.a;
    }
};
int in[N];
ll ans=0;
ll sz[N];
ll val[N];
ll sign[N];
void add(int a,int b,int c){
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void dfs(int u,int fa,ll k){
    int i;
    if(in[u]==1)
        sz[u]=1;
    for(i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(j==fa)
            continue;
        sign[j]=w[i];
        val[j]=k+w[i];
        dfs(j,u,k+w[i]);
        sz[u]+=sz[j];
    }
}
int main(){
    //ios::sync_with_stdio(false);
    int t;
    scanf("%d",&t);
    while(t--){
        priority_queue<node> q;
        int n;
        ll S;
        scanf("%d%lld",&n,&S);
        int i;
        idx=0;
        for(i=0;i<=n;i++){
            h[i]=-1;
            sz[i]=0;
            in[i]=0;
        }
        for(i=1;i<n;i++){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
            in[a]++;
            in[b]++;
        }
        dfs(1,-1,0);
        ll ans=0;
        for(i=2;i<=n;i++){
            if(in[i]==1)
            ans+=val[i];
            ll tmp=(sign[i]+1)/2*sz[i];
            q.push({tmp,i});
        }
        ll cnt=0;
        while(ans>S){
            auto tmp=q.top();
            q.pop();
            ans-=tmp.a;
            sign[tmp.b]/=2;
            q.push({(sign[tmp.b]+1)/2*sz[tmp.b],tmp.b});
            cnt++;
        }
        printf("%lld\n",cnt);
    }
    return 0;
}
View Code

 

posted @ 2020-09-04 21:02  朝暮不思  阅读(221)  评论(0编辑  收藏  举报