Link
单纯形是不可能的,这辈子都不可能单纯形的。
考虑树形dp,设(f_{u,k,p})为在(u)子树内选(k)个黑点,(u)选的黑点是(p)的最小代价。
转移和树形背包差不多,不妨设(vin son_u),考虑合并(f_{u,i,p},f_{v,j,q})。
若(p=q),则(f_{u,i,p}+f_{v,j,p}
ightarrow f_{u,i+j,p})。
若(q)在(v)子树内,则此时(p)一定不在(v)子树内,(f_{u,i,p}+f_{v,j,q}
ightarrow f_{u,i+j,p})。
若(q)在(v)子树外,不难发现此时若(p
e q)则一定不优,因此不予考虑。
#include<cstdio>
#include<vector>
#include<cstring>
#include<utility>
using i16=short;
using i64=long long;
using pi=std::pair<int,int>;
const int N=507;const i16 inf=16383;
int n,x,dfn[N],size[N],col[N],ban[N][N];i16 f[N][N][N],t[N][N];std::vector<pi>e[N];
int read(){int x;scanf("%d",&x);return x;}
void dfs1(int u,int f,int r,i64 d)
{
ban[u][r]=d>x;
for(auto[v,w]:e[u]) if(v^f) dfs1(v,u,r,d+w);
}
void dfs2(int u,int f)
{
static int t=0;dfn[u]=++t;
for(auto[v,w]:e[u]) if(v^f) dfs2(v,u);
}
void dp(int u,int fa)
{
size[u]=1;f[u][col[u]][dfn[u]]=inf,f[u][!col[u]][dfn[u]]=1;
for(int i=1;i<=n;++i) if(i^u) if(f[u][1][dfn[i]]=inf,ban[u][i]) f[u][0][dfn[i]]=inf;
for(auto[v,w]:e[u])
{
if(v==fa) continue;
dp(v,u),memset(t,0x3f,sizeof t);
for(int j=0;j<=size[v];++j)
{
i16 mn=inf;
for(int k=dfn[v];k<dfn[v]+size[v];++k) mn=std::min(mn,f[v][j][k]);
for(int i=0;i<=size[u];++i)
for(int k=1;k<=n;++k)
{
t[i+j][k]=std::min(t[i+j][k],(i16)(f[u][i][k]+f[v][j][k]));
if(k<dfn[v]||k>=dfn[v]+size[v]) t[i+j][k]=std::min(t[i+j][k],(i16)(f[u][i][k]+mn));
}
}
size[u]+=size[v],memcpy(f[u],t,sizeof t);
}
}
int main()
{
n=read(),x=read();i16 num=0;
for(int i=1;i<=n;++i) num+=col[i]=read();
for(int i=1,u,v,w;i<n;++i) u=read(),v=read(),w=read(),e[u].push_back({v,w}),e[v].push_back({u,w});
for(int i=1;i<=n;++i) dfs1(i,0,i,0);
dfs2(1,0),dp(1,0);
for(int i=0;i<=n;++i) for(int j=1;j<=n;++j) if(num>=f[1][i][j]) return !printf("%d",i);
return puts("-1"),0;
}