D. The Omnipotent Monster Killer
- 不每到一轮再考虑杀哪些,而是对怪物考虑,考虑怪物什么时候死,死前造成了多少伤害
- 不以轮数为考虑主体,而是以怪物为考虑主体
- 若当前根的怪物在wi轮死亡,wi没在之前出现过
- 则该根需要连接根为1,2,3……wi-1的树
- toti为根在i轮的树最少需要多少个节点,可以得出n个节点最大能成几轮
- tot1=1,tot2=1+1=2,tot3=1+2+1=4,tot4=1+2+4+1=8……toti=Sum { totj } + 1=2^i
- 所以有n个节点=2^i,i=log2n
- 所以最大次数为log2n
- f i j 以i为根,轮数为j
- 由于第i轮怪物先打
- f i j = ai * j + Sum{ min f v k }
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using pii = pair<int,int>;int main(){std::ios::sync_with_stdio(false);std::cin.tie(nullptr);
// long long md=(long long)998244353;
// i64 mx=LONG_LONG_MAX/2;int T;std::cin>>T;for(;T>0;--T){int n;std::cin>>n;std::vector<i64> a(n+5);for(int i=1;i<=n;++i)std::cin>>a[i];std::vector<std::vector<int>> G(n+5);for(int i=1;i<n;++i){int u,v;std::cin>>u>>v;G[u].push_back(v);G[v].push_back(u);}std::vector<std::vector<i64>> f(n+5,std::vector<i64>(22,0));auto dfs=[&](auto &&dfs,int x,int p)->void{for(int j=1;j<=21;++j) {f[x][j] = a[x] * j;}for(auto v:G[x]){if(v==p)continue;dfs(dfs,v,x);for(int j=1;j<=21;++j){i64 mi=LONG_LONG_MAX/2;for(int k=1;k<=21;++k){if(k==j)continue;mi=min(mi,f[v][k]);}f[x][j]+=mi;}}};dfs(dfs,1,0);i64 ans=LONG_LONG_MAX/2;for(int j=1;j<=21;++j)ans=min(ans,f[1][j]);std::cout<<ans<<std::endl;}}