zoukankan      html  css  js  c++  java
  • [BZOJ4557][JLOI2016]侦察守卫(树形DP)

    首先可以确定是树形DP,但这里存在跨子树的信息传递问题,这里就需要“借”的思想。

    f[i][j]表示i子树内所有点都被覆盖到,且i以外j层内的点都能被覆盖到 的方案数。

    g[i][j]表示i子树内离i距离不小于j的点都被覆盖到 的方案数。

    这里f做了一个前缀和,g做了一个后缀和。

    那么f有转移:

    1.目前以x为根的子树还有点没被覆盖到,让新加的y子树内的守卫来覆盖。

    f[x][j]=g[x][j+1]+f[k][j+1]

    2.目前x子树以完全覆盖,那么允许y子树存在未覆盖的点。

    f[x][j]=f[x][j]+g[k][j]

    同理g有转移:g[x][j]+=g[y][j-1]

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     4 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
     5 using namespace std;
     6 
     7 const int N=500010,inf=1e9;
     8 int n,m,x,u,v,d,tot,cnt,w[N],s[N],h[N],to[N<<1],nxt[N<<1],f[N][25],g[N][25];
     9 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
    10 
    11 void dfs(int x,int fa){
    12     rep(i,1,d) f[x][i]=w[x]; f[x][d+1]=inf;
    13     if (s[x]) g[x][0]=f[x][0]=w[x];
    14     For(i,x) if ((k=to[i])!=fa){
    15         dfs(k,x);
    16         rep(j,0,d) f[x][j]=min(f[x][j]+g[k][j],f[k][j+1]+g[x][j+1]);
    17         for (int j=d; ~j; j--) f[x][j]=min(f[x][j],f[x][j+1]);
    18         g[x][0]=f[x][0];
    19         rep(j,1,d) g[x][j]+=g[k][j-1];
    20         rep(j,1,d) g[x][j]=min(g[x][j],g[x][j-1]);
    21     }
    22 }
    23 
    24 int main(){
    25     freopen("bzoj4557.in","r",stdin);
    26     freopen("bzoj4557.out","w",stdout);
    27     scanf("%d%d",&n,&d);
    28     rep(i,1,n) scanf("%d",&w[i]);
    29     scanf("%d",&m);
    30     rep(i,1,m) scanf("%d",&x),s[x]=1;
    31     rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u);
    32     dfs(1,0); printf("%d
    ",g[1][0]);
    33     return 0;
    34 }
  • 相关阅读:
    在VS2010 C++中调试DLL工程的方法
    Dos命令关机、重启
    js中实现缓动效果
    win32程序窗口的创建
    win32子窗口和控件
    c++DLL添加导出函数
    Win32创建窗口的过程
    贝塞尔曲线的数学原理
    一些基本的GDI操作BITMAP的方法
    Windows快捷键
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10060408.html
Copyright © 2011-2022 走看看