HDU 6241 Color a Tree

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
", res);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/foreignbill/p/7841929.html