zoukankan      html  css  js  c++  java
  • BZOJ 4557: [JLoi2016]侦察守卫

    题目大意:
    每个点有一个放置守卫的代价,同时每个点放置守卫能覆盖到的距离都为d,问覆盖所有给定点的代价是多少。

    题解:

    树形DP

    f[x][y]表示x子树中所有点都已经覆盖完,并且x还能向上覆盖y层的最小代价。
    g[x][y]表示x的y层及以下的所有点都已经覆盖完,还需要覆盖上面的y层的最小代价。

    代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,d,cnt,m,last[1000005],f[1000005][21],g[1000005][21],vis[1000005],w[1000005];
    struct node{
    	int to,next;
    }e[1000005];
    void add(int a,int b){
    	e[++cnt].to=b;
    	e[cnt].next=last[a];
    	last[a]=cnt;
    }
    void dfs(int x,int fa){
    	if (vis[x]) f[x][0]=g[x][0]=w[x];
    	for (int i=1; i<=d; i++) f[x][i]=w[x];
    	f[x][d+1]=1e9;
    	for (int i=last[x]; i; i=e[i].next){
    		int V=e[i].to;
    		if (V==fa) continue;
    		dfs(V,x);
    		for (int j=d; j>=0; j--)
    			f[x][j]=min(f[x][j]+g[V][j],g[x][j+1]+f[V][j+1]);
    		for (int j=d; j>=0; j--)
    			f[x][j]=min(f[x][j],f[x][j+1]);
    		g[x][0]=f[x][0];
    		for (int j=1; j<=d; j++)
    			g[x][j]+=g[V][j-1];
    		for (int j=1; j<=d; j++)
    			g[x][j]=min(g[x][j],g[x][j-1]);
    	}
    }
    int main(){
    	scanf("%d%d",&n,&d);
    	for (int i=1; i<=n; i++)
    		scanf("%d",&w[i]);
    	scanf("%d",&m);
    	for (int i=1; i<=m; i++){
    		int x;
    		scanf("%d",&x);
    		vis[x]=1;
    	}
    	for (int i=1; i<n; i++){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		add(x,y);
    		add(y,x);
    	}
    	dfs(1,0);
    	printf("%d
    ",f[1][0]);
    	return 0;
    }
    

      

     

  • 相关阅读:
    Java实现 LeetCode 400 第N个数字
    Java实现 LeetCode 400 第N个数字
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 398 随机数索引
    Java实现 LeetCode 398 随机数索引
    Java实现 LeetCode 398 随机数索引
    linux中的cd ..和cd -命令有什么区别?
    GCC使用
  • 原文地址:https://www.cnblogs.com/silenty/p/9351310.html
Copyright © 2011-2022 走看看