Obviously dp
Each node consider the issue to be considered:
First: This case is covered by the following point
This contribution to the above point: second
Accordingly, we design state:
$ F [i] [j] $ $ I $ represented by a subtree of the root node has good coverage following the remaining layers, only the upper layer not covered $ $ J
$ G [i] [j] $ $ I $ represented by a subtree root node in each of points are covered, but also covering layer to the upper $ $ J
So consider moving: set root node $ x $, which is a child node $ to $
First, for $ g $: $ g [x] [j] = min (g [x] [j] + f [to] [j], f [x] [j + 1] + g [to] [j + 1]) $
The transfer principle: assume the child node needs to be covered, then the root node must cover the part before, and then use the $ j $ contribution to cover the child nodes section below
Then assume that the child node can generate contributions to the above, then you do not need to cover the part before the good, allowing the same number of layers uncovered
Next, for $ f $: $ f [x] [j] = \ sum f [to] [j-1] $
This is easy to understand, following a small upward shift covered with a new layer on the line Well
Then consider the contribution to each other between, there are: $ f [x] [j] = min (f [x] [j], f [x] [j-1]) $, $ g [x] [j] = min (g [x] [j], g [x] [j + 1]) $ i.e., we can use a smaller cost in exchange for better performance
Therefore, this problem ends
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <vector> #define ll long long using namespace std; vector <int> v[500005]; int n,m,d; bool vis[500005]; ll w[500005]; ll f[500005][25],g[500005][25]; void dfs(int x,int fx) { if(vis[x])f[x][0]=g[x][0]=w[x]; for(int i=1;i<=d;i++)g[x][i]=w[x]; g[x][d+1]=f[x][d+1]=0x3f3f3f3f3f3f3f3fll; for(int i=0;i<v[x].size();i++) { int to=v[x][i]; if(to==fx)continue; dfs(to,x); } for(int i=0;i<v[x].size();i++) { int to=v[x][i]; if(to==fx)continue; for(int j=0;j<=d;j++)g[x][j]=min(g[x][j]+f[to][j],f[x][j+1]+g[to][j+1]); for(int j=d;j>=0;j--)g[x][j]=min(g[x][j],g[x][j+1]); f[x][0]=g[x][0]; for(int j=1;j<=d;j++)f[x][j]+=f[to][j-1]; for(int j=1;j<=d;j++)f[x][j]=min(f[x][j],f[x][j-1]); } } template <typename T>inline void read(T &x) { T f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} x=c*f; } int main() { read(n),read(d); for(int i=1;i<=n;i++)read(w[i]); read(m); for(int i=1;i<=m;i++) { int x;read(x); vis[x]=1; } for(int i=1;i<n;i++) { int x,y; read(x),read(y); v[x].push_back(y),v[y].push_back(x); } dfs(1,0); printf("%lld\n",g[1][0]); return 0; }