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; }
没有人不辛苦,只有人不喊疼