CodeForces - 1099D(树上贪心+DFS)

题意:

给出一棵有根树,根节点编号为 1,每个节点存在一个权值 a[x],同时还有一个 s[x]为从根节点到节点 x 这条路径上的所有节点的 a[x]之和。此时,擦除了所有深度为偶数的节点的 s[x](根节点深度为 1)。然后要求反推出所有节点的 a[x],使得所有节点的 a[x]之和最小。

思路:

对于叶子结点来说,权值为0就行。对于s为-1的结点来说,a[x]=s[fa]-s[x],要使得a[x]最小,那么s[x]要最大,但最大不能超过x的子结点的所有的s,所以s[x]=min(s[g[x][i])。对于s已经确定的结点来说,a[x]=s[fa]-s[x]即可。

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=200005;
const int mod=1e9+7;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
vector<int> g[maxn];
int s[maxn],a[maxn],flag=1;
void dfs(int x,int fa)
{
    if(!flag)
        return ;
    if(s[x]==-1)
    {
        if(g[x].empty())
        {
            s[x]=s[fa],a[x]=0;
            return ;
        }
        int mn=inf;
        for(int i=0; i<g[x].size(); i++)
        {
            mn=min(s[g[x][i]],mn);
        }
        if(mn<s[fa])
        {
            flag=0;
            return ;
        }
        s[x]=mn,a[x]=s[x]-s[fa];
    }
    else
        a[x]=s[x]-s[fa];
    for(int i=0; i<g[x].size(); i++)
    {
        dfs(g[x][i],x);
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    int n;
    cin>>n;
    for(int i=2; i<=n; i++)
    {
        int p;
        cin>>p;
        g[p].push_back(i);
    }
    for(int i=1; i<=n; i++)
        cin>>s[i];
    s[0]=0;
    flag=1;
    dfs(1,0);
    if(!flag)
    {
        cout<<-1<<endl;
        return 0;
    }
    ll ans=0;
    for(int i=1; i<=n; i++)
        ans+=a[i];
    cout<<ans<<endl;

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值