【BZOJ3935】—RBTree(树形dp)

传送门


把距离的限制列出来好像可以单纯形做


考虑f[i][j][k]f[i][j][k]表示ii的子树中有jj个黑点,最近的点为kk的最小代价(k不一定在ii子树内)

考虑转移边uvu\rightarrow v的时候,如果u,vu,vkk一样就可以直接转移
否则是uu的在外面vv的在子树内,取vv子树内最小值即可
u,vu,v的都在外面而且不一样的话显然是没用的状态
因为这时候u,vu,v最近的点一定相同

记一下sizsiz可以做到O(n3)O(n^3)
喜提bzoj rkbzoj\ rk倒数第一

#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;
}
posted @ 2019-09-04 17:09  Stargazer_cykoi  阅读(142)  评论(0编辑  收藏  举报