hdu 6241

Posted foreignbill

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 6241相关的知识,希望对你有一定的参考价值。

Color a Tree

题目大意:一棵树,根为1.某些点有一些限制。限制A: 该$x_i$点子树染色点至少$y_i$个。 限制B: 该$x_i$点子树外染色至少$y_i$个。求最少染色点数。

首先是二分答案,二分染色的点数。check就是对于这个mid能否满足要求。

令$f1[i]$表示$i$为根的子树的最少被染色个数。
令$f2[i]$表示$i$为根的子树的最多被染色个数。

符合要求的应该是$f1[i]<=mid<=f2[i]$。

考虑到$[L,M]$与$[M+1,R]$这样的子树合并的时候要求和,考虑按dfs深度分化,或者bfs序。

$f2[i]$更新由子树和mid-子树外的点的个数决定。
$f2[i]=min(\sum son,mid-bb[i])$.

$f1[i]$更新由子树和和子树内的点限制。
$f1[i]=max(\sum son,aa[i])$.

注意坑点 aa[i] 和 bb[i] 要取最大值。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 100005;
vector<int> e[maxn];
int fa[maxn];
int Q[maxn], T, f, r;
bool vis[maxn];
int aa[maxn], bb[maxn], na, nb, u, v, n;
int f1[maxn], f2[maxn], mid;

bool dfs(int id, int fa) {
    f1[id] = 0; f2[id] = 1;
    bool ok = 1;
    for (auto ep : e[id]) {
        if (ep == fa) continue;
        ok &= dfs(ep, id);
        if (!ok) break;
    }
    if (!ok) return false;
    if (bb[id] != -1) {
        if (mid - bb[id] < f1[id]) return false;
        f2[id] = min(f2[id], mid - bb[id]);
    }
    if (aa[id] != -1) {
        if (f2[id] < aa[id]) return false;
        f1[id]=max(f1[id],aa[id]);
    }
    f1[fa] += f1[id];
    f2[fa] += f2[id];
    return true;
}

bool check(int mid) {
    f1[0] = f2[0] = 0;
    bool ok = dfs(1, 0);
    if (!ok) return false;
    if (f1[0] > mid) return false;
    if (f2[0] < mid) return false;
    return true;
}

int main() {
    //freopen("in.txt","r",stdin);
    for (cin >> T; T--;) {
        scanf("%d", &n);
        memset(aa, -1, sizeof aa);
        memset(bb, -1, sizeof bb);
        for (int i = 1; i <= n; i++)
            e[i].clear();
        for (int i = 1; i < n; i++) {
            scanf("%d%d", &u, &v);
            e[u].push_back(v);
            e[v].push_back(u);
        }
        scanf("%d", &na);
        for (int i = 1; i <= na; i++) {
            scanf("%d%d", &u, &v);
            if (aa[u] == -1) aa[u] = v;
            else aa[u] = max(aa[u], v);
        }
        scanf("%d", &nb);
        for (int i = 1; i <= nb; i++) {
            scanf("%d%d", &u, &v);
            if (bb[u] == -1) bb[u] = v;
            else bb[u] = max(bb[u], v);
        }
        int l = 1, r = n, res = -1;
        while (l <= r) {
            mid = (l + r) >> 1;
            if (check(mid))
                r = (res = mid) - 1;
            else l = mid + 1;
        }
        printf("%d\n", res);
    }
    return 0;
}

以上是关于hdu 6241的主要内容,如果未能解决你的问题,请参考以下文章

CCPC 2017 哈尔滨 L. Color a Tree && HDU 6241

HDU-3714 Error Curves(凸函数求极值)

HDU4057 Rescue the Rabbit(AC自动机+状压DP)

HDU3247 Resource Archiver(AC自动机+BFS+DP)

SQLServer常用命令

喜迎排名18