考慮這個不存在 \(\texttt{YY}\) 的限制,與 \(\texttt{XX}\) 個數為變數的限制相比較,看起來 \(\texttt{Y}\) 就更特殊,於是考慮從 \(\texttt{Y}\) 的視角來分析問題。
同時考慮到因為有 \(A + B + C = n - 1\),所以 \(\texttt{XX}\) 其實也不是很重要,因為只需要讓 \(\texttt{XY}\) 和 \(\texttt{YX}\) 的個數滿足條件就可以了。
注:這之後的分析預設遵守無 \(\texttt{YY}\),即不存在自己與父親皆為 \(\texttt{Y}\) 的情況。
於是可以考慮先讓整顆樹都是 \(\texttt{X}\),把一個 \(\texttt{X}\) 改變成 \(\texttt{Y}\) 的影響。
手玩一下可以知道若為 \(\texttt{Y}\) 的節點的集合為 \(S\),則有 \(B = |S| - [1\in S], C = \sum\limits_{u\in S} |\operatorname{son}_u|\)。
再考慮到這題的特殊條件,\(|\operatorname{son}_u| = 2 \operatorname{or} 0\)。
那麼就有 \(C = 2|S\cap \complement_{1, \cdots, n} \operatorname{leaf}|\),即 \(S\) 中非葉子結點的個數的 \(2\) 倍。
那麼能發現 \(\frac{C}{2}\) 就是 \(S\) 中非葉子結點的個數,又因為 \(B = |S| - [1\in S]\),那麼就可以知道 \(S\) 中的葉子節點個數為 \(B - \frac{C}{2} + [1\in S]\),對於這個 \([1\in S]\) 因為實際上就涉及 \(2\) 種情況是好處理的。
於是接下來的重點是是否存在 \(x\) 個非葉子節點與 \(y\) 個葉子節點的選取。
那麼一個想法是用一個樹形揹包來合併資訊,記 \(f_{u, y, x, 0 / 1}\) 為 \(u\) 節點子樹內能否存在選了 \(y\) 個葉子節點 \(x\) 個非葉子節點且自身是否選了的方案,但顯然是過不了的。
考慮到因為有 \(2\) 個限制,考慮固定下一邊的限制。
例如考慮固定下葉子節點的個數 \(y\),判定是否存在 \(x\) 個非葉子結點的個數。
能夠發現的是 \(x\) 是具有單調性的,也就是對於同樣的子樹與同樣的 \(y\) 及同樣該節點是否選取的情況,合法的 \(x\) 應當是一個字首的。
即對於同樣的 \(u, x, p\),應存在一個 \(\max x\),滿足 \(f_{u, y, x, p} = [x\le \max x]\)。
那麼就可以記 \(f_{u, y, p} = \max x\),用樹形揹包合併即可。
最後記得要討論一下 \([1\in S]\)。
時間複雜度 \(\mathcal{O}(n^2)\)。
#include<bits/stdc++.h>
constexpr int inf = 1e9;
const int maxn = 1e4 + 10;
int fa[maxn], siz[maxn];
int f[maxn][maxn][2];
int ls[maxn], rs[maxn];
inline void solve() {
int n, a, b, c; scanf("%d%d%d%d", &n, &a, &b, &c);
for (int i = 1; i <= n; i++) ls[i] = rs[i] = 0;
for (int i = 2; i <= n; i++) scanf("%d", &fa[i]), (ls[fa[i]] ? rs[fa[i]] : ls[fa[i]]) = i;
if (c & 1)
return puts("No"), void();
for (int u = n; u; u--) {
if (! ls[u]) {
siz[u] = 1;
f[u][0][0] = f[u][0][1] = 0;
f[u][1][1] = 0, f[u][1][0] = -inf;
continue;
}
siz[u] = u > 1 ? siz[ls[u]] + siz[rs[u]] : n;
for (int i = 0; i <= siz[u]; i++)
for (int j : {0, 1})
f[u][i][j] = -1e9;
for (int x : {0, 1})
for (int i = 0; i <= siz[ls[u]]; i++)
for (int j = 0; j <= siz[rs[u]]; j++)
f[u][i + j][x] = std::max(f[u][i + j][x], f[ls[u]][i][x ^ 1] + f[rs[u]][j][x ^ 1] + x);
if (u > 1)
for (int i = 0; i <= siz[u]; i++)
f[u][i][1] = std::max(f[u][i][1], f[u][i][0]);
}
puts((b >= c / 2 - 1 && f[1][b - c / 2 + 1][1] >= c / 2)
|| (b >= c / 2 && f[1][b - c / 2][0] >= c / 2) ? "Yes" : "No");
}
int main() {
int T; scanf("%d", &T);
while (T--) solve();
return 0;
}