【BZOJ3935】—RBTree(树形dp)
把距离的限制列出来好像可以单纯形做
考虑表示的子树中有个黑点,最近的点为的最小代价(k不一定在子树内)
考虑转移边的时候,如果的一样就可以直接转移
否则是的在外面的在子树内,取子树内最小值即可
若的都在外面而且不一样的话显然是没用的状态
因为这时候最近的点一定相同
记一下可以做到
喜提倒数第一
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int N=505;
ll dis[N][N],*dep;
int in[N],out[N],idx[N],dfn,inf,tot,siz[N];
int adj[N],nxt[N<<1],to[N<<1],val[N<<1],cnt;
int n,f[N][N][N],g[N][N],c[N],mxdis;
inline void addedge(int u,int v,int w){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,val[cnt]=w;
}
void dfs(int u,int fa){
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(v==fa)continue;
dep[v]=dep[u]+val[e],dfs(v,u);
}
}
void dfs2(int u,int fa){
in[u]=++dfn,idx[dfn]=u;
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(v==fa)continue;
dfs2(v,u);
}
out[u]=dfn;
}
void dp(int u,int fa){
siz[u]=1;
if(c[u])f[u][1][u]=0;
else f[u][1][u]=1;
for(int i=1;i<=n;i++)if(i!=u&&dis[i][u]<=mxdis)f[u][0][i]=0;
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(v==fa)continue;
dp(v,u);
memset(g,127/3,sizeof(g));
for(int x=0;x<=siz[u];x++)
for(int y=0;y<=siz[v];y++){
for(int k=1;k<=n;k++)chemn(g[x+y][k],f[u][x][k]+f[v][y][k]);
int res=inf;
for(int k=in[v];k<=out[v];k++)chemn(res,f[v][y][idx[k]]);
for(int k=1;k<in[v];k++)chemn(g[x+y][idx[k]],f[u][x][idx[k]]+res);
for(int k=out[v]+1;k<=n;k++)chemn(g[x+y][idx[k]],f[u][x][idx[k]]+res);
}
siz[u]+=siz[v],memcpy(f[u],g,sizeof(g));
}
}
int main(){
n=read(),mxdis=read();
for(int i=1;i<=n;i++)c[i]=read(),tot+=c[i]==1;
for(int i=1;i<n;i++){
int u=read(),v=read(),w=read();
addedge(u,v,w),addedge(v,u,w);
}
for(int i=1;i<=n;i++)dep=dis[i],dfs(i,0);
memset(f,127/3,sizeof(f));inf=f[0][0][0];
dfs2(1,0);
dp(1,0);
int res=inf;
for(int i=1;i<=n;i++)chemn(res,f[1][tot][i]);
if(res==inf)cout<<-1;
else cout<<res;
}