树形DP

树形DP

Tree painting

#include <bits/stdc++.h>
#include<stdint.h>
#define int long long
#define scan(n) scanf("%lld", &(n))
#define scann(n, m) scanf("%lld%lld", &(n), &(m))
#define scannn(a, b, c) scanf("%lld%lld%lld", &(a), &(b), &(c))
#define prin(n) printf("%lld", (n))
#define pb push_back
#define mp make_pair
#define ms(a) memset(a, 0, sizeof(a))
#define fo(i, a, b) for (int i = (a); i <= (b); i++)
#define ro(i, a, b) for (int i = (a); i >= (b); i--)
const int inf = 0x3f3f3f3f;
using namespace std;
const int maxn = 2e5+100;
vector<int>e[maxn];
int siz[maxn];
int ans,n;
int u,v;
void getsize(int v,int u){
    siz[v]=1;
    for(int x:e[v]){
        if(x==u)continue;
        getsize(x,v);
        siz[v]+=siz[x];
    }
}
void dfs(int v,int u,int t){
    ans=max(ans,t);
    cout<<v<<" "<<u<<" "<<t<<endl;
    for(int x:e[v]){
        if(x==u)continue;
        dfs(x,v,t-2*siz[x]+n);
    }
}
int32_t main() {
    scan(n);
    fo(i,1,n-1){
        scann(u,v);
        e[u].pb(v);e[v].pb(u);
    }
    getsize(1,0);
    int t=0;
    fo(i,1,n)t+=siz[i];
    dfs(1,0,t);
    printf("%lld",ans);
    return 0;
}

[CF816E] 树上背包

注意最后求答案的时候一定是\(dp[1][i][0]\)或者是\(dp[1][i][1]\)

因为想要使用优惠券,就必须保证它们的父亲被选了,而点1就是根节点

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int inf = 1e15;
const int maxn = 5000 + 10;
int n, b;
int c[maxn], d[maxn], x[maxn];
int dp[maxn][maxn][2];
int sz[maxn];
vector<int> G[maxn];
void dfs(int u)
{
    sz[u] = 1;
    dp[u][1][0] = c[u];
    dp[u][1][1] = c[u] - d[u];
    dp[u][0][0] = 0;
    for(int v:G[u]){
        dfs(v);
        for (int i = sz[u]; i >= 0; i--)
        {
            for (int j = 0; j <= sz[v];j++)
            {
                dp[u][i + j][0] = min(dp[u][i + j][0], dp[u][i][0] + dp[v][j][0]);
                dp[u][i + j][1] = min(dp[u][i + j][1], dp[u][i][1] + dp[v][j][0]);
                dp[u][i + j][1] = min(dp[u][i + j][1], dp[u][i][1] + dp[v][j][1]);
            }
        }
        sz[u] += sz[v];
    }
}
int32_t main()
{
    scanf("%lld%lld", &n, &b);
    scanf("%lld%lld", &c[1], &d[1]);
    for (int i = 2; i <= n;i++)
    {
        scanf("%lld%lld%lld", &c[i], &d[i], &x[i]);
        G[x[i]].push_back(i);
    }
    for (int i = 0; i <= n;i++)
        for (int j = 0; j <= n;j++)
            dp[i][j][0] = dp[i][j][1] = inf;
    dfs(1);
    int ans = 0;
        for (int j = 1; j <= n; j++)
            if(dp[1][j][0]<=b||dp[1][j][1]<=b)
                ans = max(ans, j);
    cout << ans << endl;
}

[CF1324E] Maximum White Subtree

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 100;

vector<int> e[maxn];
int n;
int a[maxn], ans[maxn], d[maxn];
void dfs(int u,int fa) {
    d[u] = a[u];
    for(int v:e[u]) {
        if(v==fa)
            continue;
        dfs(v, u);
        if(d[v]>0) {
            d[u] += d[v];
        }
    }
    return;
}

void dfs2(int u,int fa) {
    ans[u] = d[u];
    for(int v:e[u]) {
        if(v==fa)
            continue;
        //换根操作
        d[u] -= max(0, d[v]);//只有d[v]大于0时,v才可能对u有贡献
        d[v] += max(0, d[u]);//d[u]大于0对v才有贡献
        dfs2(v, u);
        d[v] -= max(0, d[u]);
        d[u] += max(0, d[v]);
    }
}


int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n;i++) {
        scanf("%d", &a[i]);
        if(a[i]==0)
            a[i] = -1;
    }
    for (int i = 1; i <= n - 1;i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dfs(1, 0);
    dfs2(1, 0);
    for (int i = 1; i <= n;i++) {
        printf("%d ", ans[i]);
    }
}
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 100;

vector<int> e[maxn];
int n;
int a[maxn], ans[maxn], d[maxn];
void dfs(int u,int fa) {
    d[u] = a[u];
    for(int v:e[u]) {
        if(v==fa)
            continue;
        dfs(v, u);
        if(d[v]>0) {
            d[u] += d[v];
        }
    }
    return;
}

void dfs2(int u,int fa) {
    ans[u] = d[u];
    for(int v:e[u]) {
        if(v==fa)
            continue;
        int t = d[u];
        if(d[v]>0)
            t -= d[v];
        if(t>0)
            d[v] += t;
        dfs2(v, u);
    }
}


int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n;i++) {
        scanf("%d", &a[i]);
        if(a[i]==0)
            a[i] = -1;
    }
    for (int i = 1; i <= n - 1;i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dfs(1, 0);
    dfs2(1, 0);
    for (int i = 1; i <= n;i++) {
        printf("%d ", ans[i]);
    }
}
posted @ 2020-03-27 23:58  瓜瓜站起来  阅读(129)  评论(0编辑  收藏  举报