JLOI/SHOI2016侦查守卫
Posted aurora2004
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JLOI/SHOI2016侦查守卫相关的知识,希望对你有一定的参考价值。
SOL:
(f[i][j]i)点向上(j)层都可以被监视最小代价(当前点为第0层)
(g[i][j]i)点向下(j)层都无法别监视最小代价(当前点为第1层)
初始值:
需守卫的点:(f[x][0]=g[x][0]=w[x])
其余点:(f[x][0]=g[x][0]=0)
所有点:(f[x][i]=w[x](i>0))
转移方程:
[f[x][i]=min(f[x][i]+min(g[v][i],f[v][i+1]),g[x][i+1]+f[v][i+1])]
[f[x][i]=min(f[x][i],f[x][i+1])]
[g[x][0]=f[x][0]]
[g[x][i]+=g[v][i-1]]
[g[x][i]=min(g[x][i],g[x][i-1])]
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f==1?x:-x;
}
const int N=5e5+4,D=24;
int n,m,d,a[N],f[N][D],g[N][D],w[N];
vector<int>e[N];
void dfs(int x,int fa){
if(a[x])f[x][0]=g[x][0]=w[x];
else f[x][0]=g[x][0]=0;
for(int i=1;i<=d;i++)f[x][i]=w[x];
for(auto v:e[x]){
if(v==fa)continue;
dfs(v,x);
for(int i=d;i>=0;i--){
f[x][i]=min(min(f[x][i]+g[v][i],g[x][i+1]+f[v][i+1]),f[x][i]+f[v][i+1]);
f[x][i]=min(f[x][i+1],f[x][i]);
}
g[x][0]=f[x][0];
for(int i=1;i<=d+1;i++){
g[x][i]=g[x][i]+g[v][i-1];
g[x][i]=min(g[x][i],g[x][i-1]);
}
}
}
int main(){
n=read();d=read();
for(int i=1;i<=n;i++)w[i]=read();
m=read();
for(int i=1;i<=m;i++)a[read()]=1;
for(int i=1,u,v;i<n;i++){
u=read();v=read();
e[u].push_back(v);e[v].push_back(u);
}
memset(f,0x3f,sizeof(f));
dfs(1,0);
cout<<f[1][0];
return (0-0);
}
以上是关于JLOI/SHOI2016侦查守卫的主要内容,如果未能解决你的问题,请参考以下文章