[hdu 6241 Color a Tree]二分+树形DP
分类:Binary Search
1. 题目链接
2. 题意描述
一棵
n
个节点的有根树。现在对它进行染色。有
其中有
A
个条件为,第
问最少需要染多少个顶点。
3. 解题思路
首先,二分需要染色的顶点个数。
设当前二分的染色顶点个数为
num
,那么对于第二种限制条件,可以转化为第
xi
个节点的子树下染色顶点数目必须小于或等于
num−yi
。那么,每次check的时候,只需要dfs求出每个节点为根节点的子树下最多、最少分别能染多少个节点。
这题思路好像并不是很难,但是Debug了好久惹。
4. 实现代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll infl = 0x3f3f3f3f3f3f3f3fLL;
template<typename T> inline void umax(T &a, T b) { a = max(a, b); }
template<typename T> inline void umin(T &a, T b) { a = min(a, b); }
void debug() { cout << endl; }
template<typename T, typename ...R> void debug (T f, R ...r) { cout << "[" << f << "]"; debug (r...); }
const int MAXN = 100005;
int n;
vector<int> G[MAXN];
int A[MAXN], B[MAXN], C[MAXN];
int siz[MAXN];
void dfs_pre(int u, int fa) {
siz[u] = 1;
int cnt = 0;
for (auto& v : G[u]) {
if (v == fa) continue;
dfs_pre(v, u);
siz[u] += siz[v];
cnt += A[v];
}
umax(A[u], cnt);
}
void dfs_max(int u, int fa) {
int cnt = 1;
for (auto& v : G[u]) {
if (v == fa) continue;
dfs_max(v, u);
cnt += C[v];
}
umin(C[u], cnt);
}
bool check(int x) {
for (int i = 1; i <= n; ++i) {
C[i] = x - B[i];
if (C[i] < A[i] || A[i] > siz[i]) return false;
umin(C[i], siz[i]);
}
dfs_max(1, 0);
// for (int i = 1; i <= n; ++i) debug(i, A[i], C[i]);
for (int i = 1; i <= n; ++i) if (C[i] < A[i]) return false;
return C[1] >= x;
}
int main() {
#ifdef ___LOCAL_WONZY___
freopen("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
int u, v, T; cin >> T;
while (T --) {
cin >> n;
for (int i = 1; i <= n; ++i) {
G[i].clear();
A[i] = B[i] = 0;
}
for (int i = 2; i <= n; ++i) {
scanf("%d %d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
int na; cin >> na;
for (int i = 1; i <= na; ++i) {
scanf("%d %d", &u, &v);
umax(A[u], v);
}
int nb; cin >> nb;
for (int i = 1; i <= nb; ++i) {
scanf("%d %d", &u, &v);
umax(B[u], v);
}
dfs_pre(1, 0);
int lb = A[1], ub = n, md, ans = -1;
while (lb <= ub) {
md = (lb + ub) >> 1;
if (check(md)) ans = md, ub = md - 1;
else lb = md + 1;
}
printf("%d\n", ans);
}
#ifdef ___LOCAL_WONZY___
cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << "ms." << endl;
#endif // ___LOCAL_WONZY___
return 0;
}