zoukankan      html  css  js  c++  java
  • 树形DP【洛谷P3047】 [USACO12FEB]附近的牛Nearby Cows

    P3047 [USACO12FEB]附近的牛Nearby Cows

    农民约翰已经注意到他的奶牛经常在附近的田野之间移动。考虑到这一点,他想在每一块土地上种上足够的草,不仅是为了最初在这片土地上的奶牛,而且是为了从附近的田地里去吃草的奶牛。

    具体来说,FJ的农场由N块田野构成(1 <= n <= 100,000),每两块田野之间有一条无向边连接(总共n-1条边)。FJ设计了农场,任何两个田野i和j之间,有且只有一条路径连接i和j。第 i块田野是C(i)头牛的住所,尽管奶牛们有时会通过k条路到达其他不同的田野(1<=k<=20)。

    FJ想在每块田野上种上够M(i)头奶牛吃的草。M(i)指能从其他点经过最多k步就能到达这个点的奶牛的个数。

    现给出FJ的每一个田野的奶牛的数目,请帮助FJ计算每一块田野的M(i)。

    先处理出来子树内的。

    (f(i)(j))表示以i为根的子树内距离i为j的答案。

    很简单的转移:

    (f(u)(j)=sum_{f(v)(j-1)}​)

    然后转移出非子树内的,为了解决DP后效性要开一个中间量数组转移一下。

    code:

    #include <iostream>
    #include <cstdio>
    
    #define int long long
    
    using namespace std;
    
    const int wx=100017;
    
    inline int read(){
    	int sum=0,f=1; char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    	return sum*f;
    }
    
    int f[wx][27],g[wx][27];
    int head[wx],val[wx];
    int n,k,num;
    
    struct e{
    	int nxt,to;
    }edge[wx*2];
    
    void add(int from,int to){
    	edge[++num].nxt=head[from];
    	edge[num].to=to;
    	head[from]=num;
    }
    
    void dfs(int u,int fa){
    	f[u][0]=val[u];
    	for(int i=head[u];i;i=edge[i].nxt){
    		int v=edge[i].to;
    		if(v==fa)continue;
    		dfs(v,u);
    		for(int j=1;j<=k;j++){
    			f[u][j]=(f[u][j]+f[v][j-1]);
    		}
    	}
    }
    
    void dp(int u,int fa){
    	for(int i=head[u];i;i=edge[i].nxt){
    		int v=edge[i].to;
    		if(v==fa)continue;
    		g[v][1]+=f[u][0];
    		for(int j=2;j<=k;j++){
    			g[v][j]+=(f[u][j-1]-f[v][j-2]);
    		}
    		for(int j=1;j<=k;j++)f[v][j]+=g[v][j];
    		dp(v,u);
    	}
    }
    
    signed main(){
    //	freopen("a.in","r",stdin);
    //	freopen("a.out","w",stdout);
    	n=read(); k=read();
    	for(int i=1;i<n;i++){
    		int x,y;
    		x=read(); y=read();
    		add(x,y); add(y,x);
    	}
    	for(int i=1;i<=n;i++)val[i]=read();
    	dfs(1,0); dp(1,0);
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=k;j++){
    			f[i][j]+=f[i][j-1];
    		}
    	}
    	for(int i=1;i<=n;i++)printf("%lld
    ",f[i][k]);
    	
    	return 0;
    }
    
  • 相关阅读:
    asp数据查询及数据筛选
    数据链接(无源方式)
    HTML5 Input 类型
    PS调出米黄色复古柔和外景人物照
    PS调出清新淡雅外景女生背影照
    PS提亮户外儿童照
    PS制作恐怖逼真滴血文字
    ps昏暗室内照片调成暖色光亮效果
    PS滤镜制作下雨照片特效
    PS滤镜给城市夜空照片添加满天星
  • 原文地址:https://www.cnblogs.com/wangxiaodai/p/9877457.html
Copyright © 2011-2022 走看看