CF1988D

他妈的我怎么这么唐。

需要观察性质,这个所谓的删除最多进行 \(\log n\) 步。这是因为一轮删除后一个点被保留当且仅当跟他相连的点有一个被选。即每次删除会让极大联通块大小减半。

然后就唐完了。我赛时以为策略是删除 \(\log n\) 次最大权独立集,然后这个是假的,然后就唐完了。

不妨设 \(f_{x,i}\)\(x\) 子树内,\(x\)\(i\) 次被 删除的最小代价。一个儿子的 \(f_{v,j}\) 能向 \(f_{x.i}\) 转移当且仅当 \(i\ne j\)。然后就做完了。

朴素实现 \(O(n\log^2n)\)

#include<iostream>
#include<vector>
#define pb push_back
const int N = 3e5 + 10;
std::vector<int> g[N];
int t, n; long long f[N][21], a[N];
void dfs(int x, int fa){
    for(int i = 1; i <= 20; i++) f[x][i] = 1ll * a[x] * i;
    for(auto v:g[x]) if(v != fa){
        dfs(v, x); for(int j = 1; j <= 20; j++){
            long long mx = 9e18;
            for(int k = 1; k <= 20; k++)
                if(j != k) mx = std::min(mx, f[v][k]);
            f[x][j] += mx;
        }
    }
}
int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(0),std::cout.tie(0);
    std::cin >> t; while(t--){
        std::cin >> n; long long rs = 9e18;
        for(int i = 1; i <= n; i++) std::cin >> a[i], g[i].clear();
        for(int i = 1, x, y; i < n; i++)
            std::cin >> x >> y, g[x].pb(y), g[y].pb(x);
        dfs(1, 0); long long mx = 9e18;
        for(int i = 1; i <= 20; i++)
        	mx = std::min(mx, f[1][i]);
        std::cout << mx << '\n';
    }
}
posted @ 2024-07-24 21:29  xlpg0713  阅读(9)  评论(0)    收藏  举报