CF-1249 F.Maximum Weight Subset(贪心)

CF-1249 F.Maximum Weight Subset(贪心)

题目链接

题意

CF-1249 F.Maximum Weight Subset(贪心)_第1张图片
在一棵树上选一些点构成一个集合,满足集合内任意两点的距离大于 k k k,求集合的最大权值和

思路

一共200个点,可以从最低层的点 u u u开始,默认选择这个点,然后将它距离 k k k的点权值减小 v a l [ u ] val[u] val[u]表示这些点不选.

这样向上找的时候如果碰到权值为正的点,表示选择这个点的权值更优,同时不会影响其他点

复杂度 O ( n 2 ) O(n^2) O(n2)

#include 
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
using namespace std;
vector<int> g[maxn];
int a[maxn], b[maxn], dep[maxn], n, k;
void dfs(int u, int fa, int d) {
    dep[u] = d;
    for (auto v : g[u]) {
        if (fa == v) continue;
        dfs(v, u, d+1);
    }
}
void dfs(int u, int fa, int x, int d) {
    if (d > k) return;
    a[u] -= x;
    for (auto v : g[u]) {
        if (fa == v) continue;
        dfs(v, u, x, d+1);
    }
}
int main() {
    cin >> n >> k;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1, 0, 0);
    for (int i = 1; i <= n; ++i) b[i] = i;
    sort(b+1, b+1+n, [&](int x, int y){
        return dep[x] > dep[y];
    });
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        if (a[b[i]] <= 0) continue;
        ans += a[b[i]];
        dfs(b[i], 0, a[b[i]], 0);
    }
    cout << ans << endl;
    return 0;
}

你可能感兴趣的:(基础算法)