HDU 6241Color a Tree——二分+树形dp

版权声明:欢迎大家转载,转载请注明出处 https://blog.csdn.net/hao_zong_yin/article/details/82703382

A限制用树形dp就可以做,B限制一开始想维护一下父亲,兄弟等信息,但怎么都维护不出来,然后突然想到可以二分答案x,每个节点只要有A的信息以及答案x就可以得到B的信息了,想到以后扫了一遍点,判了一下dp[i]+b[i]是否小于x,WA了...

这是因为节点a满足条件,节点b满足条件,但是节点ab不一定同时满足条件,因此我们应该讲刚才的做法转化一下,x-b[i]转化为i的子树的上限,这样每次二分的时候来一遍树形dp就可以做了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 1e5 + 10;
int t, n;
vector<int> g[maxn];
int a[maxn], b[maxn], sz[maxn], down[maxn], up[maxn];
void dfs(int f, int u) {
    sz[u] = 1;
    for (int i = 0; i < g[u].size(); i++) {
        int v = g[u][i];
        if (v == f) continue;
        dfs(u, v);
        sz[u] += sz[v];
    }
}
bool judge(int f, int u) {
    int D = 0, U = 1;
    for (int i = 0; i < g[u].size(); i++) {
        int v = g[u][i];
        if (v == f) continue;
        if (!judge(u, v)) return false;
        D += down[v];
        U += up[v];
    }
    down[u] = max(down[u], D);
    up[u] = min(up[u], U);
    return down[u] <= up[u];
}
int binarysearch() {
    for (int i = 1; i <= n; i++) down[i] = a[i];
    int l = 0, r = n;
    while (l <= r) {
        int m = (l + r)>>1;
        for (int i = 1; i <= n; i++) up[i] = min(sz[i], m - b[i]);
        if (judge(0, 1) && down[1] <= m && m <= up[1]) r = m - 1;
        else l = m + 1;
    }
    return l;
}
int main() {
    scanf("%d", &t);
    while (t--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) g[i].clear();
        for (int i = 1; i <= n-1; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        for (int i = 1; i <= n; i++) a[i] = b[i] = 0;
        int A;
        scanf("%d", &A);
        for (int i = 1; i <= A; i++) {
            int x, y;
            scanf("%d%d", &x, &y);
            a[x] = max(a[x], y);
        }
        int B;
        scanf("%d", &B);
        for (int i = 1; i <= B; i++) {
            int x, y;
            scanf("%d%d", &x, &y);
            b[x] = max(b[x], y);
        }
        dfs(0, 1);
        bool ok = true;
        for (int i = 1; i <= n; i++) {
            if (a[i] > sz[i] || b[i] > n - sz[i]) { ok = false; break; }
        }
        if (!ok) { puts("-1"); continue; }
        else printf("%d\n", binarysearch());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hao_zong_yin/article/details/82703382