P3047 [USACO12FEB]Nearby Cows G

P3047 [USACO12FEB]Nearby Cows G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

树上思维好题

这道题不是树形dp,但是我们要用树形dp的思维来做这题.

首先我们令:dp[x][i]为在x的子树中,与x不超过i距离节点的权值之和。

显然这是很容易求的

void dfs1(int x,int fa)
{
    dp[x][0]=a[x];
    for(auto v:g[x])
    {
        if(v==fa) continue;
        dfs1(v,x);
    }
    for(int i=1;i<=k;i++)
    {
        dp[x][i]=a[x];
        for(auto v:g[x])
        {
            if(v==fa) continue;
            dp[x][i]+=dp[v][i-1];
        }
    }
}

接着我们令:f[x][i]为在与x不超过i距离节点的权值之和

 

 以1作为1号节点,1为2的父节点。上面是特地让图好看一些

首先有f[1][i]=dp[1][i],因为i为根节点

现在求与2节点不超过距离为2的节点权值和f[2][2],主要便是求不属于2节点子树的点。

对于不是2节点子树的点,便是包括在与1节点距离不超过1的点(9,7,8,2),这部分是f[1][1].

但是与1节点距离不超过1的点还包括 2节点 这种不合理点,这不合理部分是dp[1][1]还是dp[2][0]?显然dp[2][0](2),dp[1][1](9,7,8,2).

所以:f[2][2]=dp[2][2]+(f[1][1]-dp[2][0]);

则:if(i>=2) f[v][i]=dp[v][i]+(f[v][i-1]-dp[v][i-2])

   if(i==1) f[v][1]=dp[v][i]+a[x];

    if(i==0) f[v][0]=d[v][0];

void dfs2(int x,int fa)
{
    if(x==1)
        for(int i=1;i<=k;i++) f[1][i]=dp[1][i];
    for(auto v:g[x])
    {
        if(v==fa) continue;
        f[v][0]=dp[v][0];
        f[v][1]=dp[v][1]+a[x];
        for(int i=2;i<=k;i++) f[v][i]=dp[v][i]+(f[x][i-1]-dp[v][i-2]);
        dfs2(v,x);
    }
}

Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pb push_back   
#define popb pop_back  
#define fi first
#define se second
const int N=1e5+10;
//const int M=;
//const int inf=0x3f3f3f3f;     
//const ll INF=0x3ffffffffffff;
int T,n,k,a[N],dp[N][30],f[N][30];
vector<int> g[N];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
void dfs1(int x,int fa)
{
    dp[x][0]=a[x];
    for(auto v:g[x])
    {
        if(v==fa) continue;
        dfs1(v,x);
    }
    for(int i=1;i<=k;i++)
    {
        dp[x][i]=a[x];
        for(auto v:g[x])
        {
            if(v==fa) continue;
            dp[x][i]+=dp[v][i-1];
        }
    }
}
void dfs2(int x,int fa)
{
    if(x==1)
        for(int i=1;i<=k;i++) f[1][i]=dp[1][i];
    for(auto v:g[x])
    {
        if(v==fa) continue;
        f[v][0]=dp[v][0];
        f[v][1]=dp[v][1]+a[x];
        for(int i=2;i<=k;i++) f[v][i]=dp[v][i]+(f[x][i-1]-dp[v][i-2]);
        dfs2(v,x);
    }
}
int main()
{
//    freopen("","r",stdin);
//    freopen("","w",stdout);
    n=read(),k=read(); 
    for(int i=1;i<n;i++)
    {
        int u=read(),v=read();
        g[u].pb(v);
        g[v].pb(u);
    }
    for(int i=1;i<=n;i++) a[i]=read();
    dfs1(1,0);
    dfs2(1,0);
    for(int i=1;i<=n;i++) printf("%d\n",f[i][k]);
    return 0;
}

 

posted @ 2023-03-12 21:00  QAQ啥也不会  阅读(20)  评论(0编辑  收藏  举报