bzoj 4557

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;
}

 

Guess you like

Origin www.cnblogs.com/zhangleo/p/11140971.html