设f[x][j]表示覆盖以x为根的子树的所有应该被覆盖的节点,并且以x为根的子树向下j层全部被覆盖的最小代价。
设g[x][j]表示与x距离大于j全部应该覆盖的节点全部被覆盖的最小代价。
有
f[u][j] = min{f[u][j]+g[v][j],g[u][j+1]+f[v][j+1],f[u][j+1]}
g[u][j] = min{g[u][j-1],g[u][j]+g[v][j-1]}
边界f[u][d+1] = inf;f[u][i] = c[u];(i <= d) f[u][0] = c[u] or 0
g[u][0] = f[u][0];
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 typedef long long ll; 8 inline void read(int &x){ 9 x=0;char ch;bool flag = false; 10 while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true; 11 while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x; 12 } 13 inline int cat_max(const ll &a,const ll &b){return a>b ? a:b;} 14 inline int cat_min(const ll &a,const ll &b){return a<b ? a:b;} 15 const int maxn = 500010; 16 const int maxd = 24; 17 struct Edge{ 18 int to,next; 19 }G[maxn<<1]; 20 int head[maxn],cnt; 21 void add(int u,int v){ 22 G[++cnt].to = v; 23 G[cnt].next = head[u]; 24 head[u] = cnt; 25 } 26 ll f[maxn][maxd],g[maxn][maxd]; 27 int c[maxn],fa[maxn],d; 28 bool h[maxn]; 29 #define v G[i].to 30 void dfs(int u){ 31 if(h[u]) f[u][0] = g[u][0] = c[u]; 32 else f[u][0] = g[u][0] = 0; 33 for(int i=1;i<=d;++i) f[u][i] = c[u]; 34 f[u][d+1] = 1000LL*maxn; 35 for(int i = head[u];i;i=G[i].next){ 36 if(v == fa[u]) continue; 37 fa[v] = u; 38 dfs(v); 39 for(int j=d;j>=0;--j){ 40 f[u][j] = cat_min(cat_min(f[u][j]+g[v][j],g[u][j+1]+f[v][j+1]),f[u][j+1]); 41 } 42 g[u][0] = f[u][0]; 43 for(int j=1;j<=d+1;++j){ 44 g[u][j] = cat_min(g[u][j-1],g[u][j] + g[v][j-1]); 45 } 46 } 47 } 48 #undef v 49 int main(){ 50 51 int n;read(n);read(d); 52 for(int i=1;i<=n;++i) read(c[i]); 53 int m;read(m); 54 for(int i=1,x;i<=m;++i) read(x),h[x] = true; 55 for(int i=1,u,v;i<n;++i){ 56 read(u);read(v); 57 add(u,v);add(v,u); 58 } 59 dfs(1); 60 printf("%lld ",g[1][0]); 61 getchar();getchar(); 62 return 0; 63 }