CF375E Red and Black Tree
Solution
非常神奇的一道题。
我们不考虑交换操作,相反,我们去考虑把多少个 \(0\) 的位置变为 \(1\),同时我们记录选了多少个黑点,如果跟原来黑点数量相同即是合法。
此时我们可以发现一个神奇的性质对于 \(u\) 的儿子 \(v\),如果覆盖 \(u\) 的节点不覆盖 \(v\),那么覆盖 \(v\) 的节点在 \(v\) 的子树内的时候最优,因为不在的话会让覆盖 \(u\) 的节点变成覆盖 \(v\) 的节点。
所以我们可以考虑设 \(f_{u,i,k}\) 表示以 \(u\) 为根的子树,选了 \(i\) 个黑点,覆盖 \(u\) 的节点是 \(k\) 的最小需要把多少个白点变为黑点,然后我们可以树上背包。复杂度显然 \(\Theta(n^3)\)。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define MAXN 505
#define sh short
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
#define pii pair<int,int>
#define se second
#define fi first
vector <pii> g[MAXN];
int n,X,tot,col[MAXN];
sh f[MAXN][MAXN][MAXN],h[MAXN][MAXN],miv[MAXN][MAXN];
int ind,tur[MAXN],dfn[MAXN],siz[MAXN];
void dfs (int u,int fa){
dfn[u] = ++ ind,tur[ind] = u;
for (pii it : g[u]){
int v = it.fi;
if (v ^ fa) dfs (v,u);
}
}
void getdis (int u,int rt,int fa,int dis){
if (u == rt) f[u][1][dfn[u]] = 1 ^ col[u];
else f[rt][0][dfn[u]] = 0;
for (pii it : g[u]){
int v = it.fi,w = it.se;
if (v != fa && dis + w <= X) getdis (v,rt,u,dis + w);
}
}
void dfs1 (int u,int fa){
siz[u] = 1;
for (pii it : g[u]){
int v = it.fi;
if (v == fa) continue;
dfs1 (v,u);
for (Int i = 0;i <= siz[u];++ i) for (Int t = 1;t <= n;++ t) h[i][t] = f[u][i][t],f[u][i][t] = 0x3f3f;
for (Int i = 0;i <= siz[u];++ i) for (Int t = 1;t <= n;++ t){
for (Int j = 0;j <= siz[v] && i + j <= tot;++ j){
chkmin (f[u][i + j][t],(sh)(h[i][t] + f[v][j][t]));
if (t < dfn[v] || t >= dfn[v] + siz[v])
chkmin (f[u][i + j][t],(sh)(h[i][t] + miv[v][j]));
}
}
siz[u] += siz[v];
}
for (Int i = 0;i <= siz[u];++ i){
miv[u][i] = 0x3f3f;
for (Int k = dfn[u];k <= dfn[u] + siz[u] - 1;++ k) chkmin (miv[u][i],f[u][i][k]);
}
}
signed main(){
read (n,X);
for (Int x = 1;x <= n;++ x) read (col[x]),tot += col[x];
for (Int i = 2,u,v,w;i <= n;++ i) read (u,v,w),g[u].push_back ({v,w}),g[v].push_back ({u,w});
dfs (1,0),memset (f,0x3f,sizeof (f));
for (Int u = 1;u <= n;++ u) getdis (u,u,u,0);
dfs1 (1,0);sh ans = n + 1;
for (Int i = 0;i <= tot;++ i)
for (Int j = 1;j <= n;++ j)
chkmin (ans,f[1][i][j]);
write (ans == n + 1 ? -1 : ans),putchar ('\n');
return 0;
}