Considering the tree DP, suppose we have considered the placement of listening points in the current subtree, and the root is u u u. Consider what status we want to record: u u u how far can the monitoring point in the subtree be monitored outside the subtree, u u How far is the UN monitored point farthest from the root in the u subtree.
It is found that when the second state exists, the first state is useless because if u u There is an un monitored point in the u subtree v v v. Set it to u u The distance of u is d d d. Then:
- u u u the farthest listening distance from the listening point in the subtree to the outside of the subtree will not exceed d d d. Otherwise v v v can be monitored.
- v v v must finally be u u A point outside the u subtree x x x monitor, then all distances u u u less than or equal to d d All points of d can be x x I heard it.
That is, when v v When v exists, we don't need to consider it u u Listening points in u subtree u u For the monitoring outside the u subtree, the first state is useless.
Then this simplifies the DP state: let's set f u , i f_{u,i} fu,i , means considered u u The placement of monitoring points in u subtree, u u u subtree inner separation u u u the distance of the farthest point not monitored is i i i. Minimum cost required. set up g u , i g_{u,i} gu,i , indicates that consideration has been completed u u The placement of monitoring points in u subtree, u u There are no un monitored points in the u subtree, and u u The farthest listening distance from the listening point in the u subtree to the outside of the subtree i i i. Minimum cost required.
Merge on transfer
u
u
u currently considered subtrees and enumerated sons
v
v
Subtree of v, min
f
u
,
f
v
f_u,f_v
fu,fv,
f
u
,
g
v
f_u,g_v
fu,gv,
g
u
,
f
v
g_u,f_v
gu,fv,
g
u
,
g
v
g_u,g_v
gu, gv# four cases are combined:
f
u
,
i
+
f
v
,
j
→
f
u
,
max
(
i
,
j
+
1
)
f
u
,
i
+
g
v
,
j
→
{
g
u
,
j
−
1
if
j
−
1
≥
i
f
u
,
i
if
j
−
1
<
i
g
u
,
i
+
f
v
,
j
→
{
g
u
,
i
if
i
≥
j
+
1
f
u
,
j
+
1
if
i
<
j
+
1
g
u
,
i
+
g
v
,
j
→
g
u
,
max
(
i
,
j
−
1
)
\begin{aligned} f_{u,i}+f_{v,j}&\to f_{u,\max(i,j+1)}\\ f_{u,i}+g_{v,j}&\to \begin{cases}g_{u,j-1}&\text{if }j-1\geq i\\f_{u,i}&\text{if }j-1<i\end{cases}\\ g_{u,i}+f_{v,j}&\to \begin{cases}g_{u,i}&\text{if }i\geq j+1\\f_{u,j+1}&\text{if }i<j+1\end{cases}\\ g_{u,i}+g_{v,j}&\to g_{u,\max(i,j-1)} \end{aligned}
fu,i+fv,jfu,i+gv,jgu,i+fv,jgu,i+gv,j→fu,max(i,j+1)→{gu,j−1fu,iif j−1≥iif j−1<i→{gu,ifu,j+1if i≥j+1if i<j+1→gu,max(i,j−1)
This can be done using prefixes and / or suffixes and optimizations
O
(
n
D
)
O(nD)
O(nD).
Initially, each point forms a separate subtree, which is set for all points g u , D ← w u g_{u,D}\gets w_u gu,D ← wu, set the point to be monitored f u , 0 = 0 f_{u,0}=0 fu,0 = 0, set for points that do not need to be monitored g u , 0 = 0 g_{u,0}=0 gu,0=0.
#include<bits/stdc++.h> #define D 25 #define N 500010 #define INF 0x7fffffff using namespace std; inline void upmin(int &x,int y){if(y<x) x=y;} inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^'0'); ch=getchar(); } return x*f; } int n,d,w[N]; int cnt,head[N],nxt[N<<1],to[N<<1]; int f[N][D],g[N][D],pref[N][D],preg[N][D]; void adde(int u,int v) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } inline void premin(int *f,int *pre) { for(int i=0;i<=d;i++) pre[i]=min(i?pre[i-1]:INF,f[i]); } void dfs(int u,int fa) { static int ff[D],gg[D]; premin(f[u],pref[u]),premin(g[u],preg[u]); for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(v==fa) continue; dfs(v,u); memset(ff,0x3f,sizeof(ff)); memset(gg,0x3f,sizeof(gg)); for(int i=1;i<=d;i++) upmin(ff[i],f[u][i]+pref[v][i-1]); for(int i=0;i<d;i++) upmin(ff[i+1],pref[u][i+1]+f[v][i]); for(int i=1;i<=d;i++) upmin(gg[i-1],pref[u][i-1]+g[v][i]); for(int i=0;i<=d;i++) upmin(ff[i],f[u][i]+preg[v][i]); for(int i=1;i<=d;i++) upmin(gg[i],g[u][i]+pref[v][i-1]); for(int i=0;i<d;i++) upmin(ff[i+1],preg[u][i]+f[v][i]); for(int i=0;i<=d;i++) upmin(gg[i],g[u][i]+preg[v][min(i+1,d)]); for(int i=1;i<=d;i++) upmin(gg[i-1],preg[u][i-1]+g[v][i]); memcpy(f[u],ff,sizeof(f[u])); memcpy(g[u],gg,sizeof(g[u])); premin(f[u],pref[u]),premin(g[u],preg[u]); } } int main() { n=read(),d=read(); memset(f,0x3f,sizeof(f)); memset(g,0x3f,sizeof(g)); for(int i=1;i<=n;i++) g[i][d]=read(); for(int i=1,m=read();i<=m;i++) f[read()][0]=0; for(int i=1;i<=n;i++) if(f[i][0]) g[i][0]=0; for(int i=1;i<n;i++) { int u=read(),v=read(); adde(u,v),adde(v,u); } dfs(1,0); int ans=INF; for(int i=0;i<=d;i++) ans=min(ans,g[1][i]); printf("%d\n",ans); return 0; }