[JLOI2016]
- 菜的真实,不会写
- f[x][j]表示从x开始向下j层(包括x)以下都被覆盖的最小花费
- g[x][j]表示x及x的子树都覆盖完了,x向上还能覆盖j层的最小花费
- 如果选x:g[x][j]=g[x][j]+f[y][j]
- 如果选y:g[x][j]=g[y][j+1]+f[x][j+1]
- f[x][j]=\sum f[y][j-1]
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int inf=1e9;
const int N=5e5+100;
struct node{int y,n;}e[N<<1];
int lin[N<<1],f[N][25],g[N][25],w[N],v[N],len,n,d,m,x,y;
inline int read(){
int num=0;char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))num=num*10+ch-'0',ch=getchar();
return num;
}
void LK(int x,int y)
{e[++len].y=y,e[len].n=lin[x],lin[x]=len;}
void init(){
n=read(),d=read();
rep(i,1,n)w[i]=read();
m=read();
rep(i,1,m)x=read(),v[x]=1;
rep(i,2,n){
x=read(),y=read();
LK(x,y),LK(y,x);
}
}
void dfs(int x,int fa){
if(v[x])f[x][0]=g[x][0]=w[x];
rep(i,1,d)g[x][i]=w[x]; g[x][d+1]=inf;
for(int i=lin[x];i;i=e[i].n){
int y=e[i].y;
if(y==fa)continue;
dfs(y,x);
per(j,d,0)g[x][j]=min(g[x][j]+f[y][j],g[y][j+1]+f[x][j+1]);
per(j,d,0)g[x][j]=min(g[x][j],g[x][j+1]);
f[x][0]=g[x][0];
rep(j,1,d+1)f[x][j]+=f[y][j-1];
rep(j,1,d+1)f[x][j]=min(f[x][j],f[x][j-1]);
}
}
int main()
{
//freopen("a.in","r",stdin);
init();
dfs(1,1);
cout<<f[1][0];
return 0;
}