皇宫看守(树形dp)

1077. 皇宫看守 - AcWing题库

这个题容易与战略游戏混起来,战略游戏是每条边的两端点必须有守卫,也就是边的特性,而这题是点的两端必须有守卫,对于战略游戏来说101可以,1001不可以,而1001皇宫这题是可以的,所以我在dp[a]二维数组中加了一个dp[a][2]表示此点不放守卫但是可以以后被父节点表示的情况,还有一个坑点是,dp[a][0]与战略游戏不同,战略游戏dp[a][0]所连的每条边的另一端点都必须有守卫,而皇宫这题则不需要,只需要一个子点有守卫即可,而在遍历的时候会发现,所有子节点的min(dp[son][1],dp[son][0]和已经被统计过,可以直接拿出来用。所以这题就被写出来了。

#include<bits/stdc++.h>
using namespace std;
#define ll  long long
#define INF 9223372036854775807
ll nex[1000001],head[1000001],edge[1000001],val[1000001];
ll dp[5000][3];
ll ans=-1,m;
ll cnt=0;
void dfs(ll a,ll fa)
{
    for(ll i=head[a];i;i=nex[i])
    {
        ll son=edge[i];
        if(fa==son) continue;
        dfs(son,a);
        dp[a][2]+=min(dp[son][1],dp[son][0]);
        dp[a][1]+=min(dp[son][1],min(dp[son][0],dp[son][2]));
    }
    for(ll i=head[a];i;i=nex[i])
    {
        ll son=edge[i];
        if(son==fa) continue;
        dp[a][0]=min(dp[a][0],dp[a][2]-min(dp[son][1],dp[son][0])+dp[son][1]);
    }
    dp[a][1]+=val[a];
}
void add(ll a,ll b)
{
    edge[++cnt]=b;
    nex[cnt]=head[a];
    head[a]=cnt;
}
void solve()
{
    ll n,a,b,c;
    cin>>n;
    for(ll i=1;i<=n;i++)
    {
        cin>>a;
        cin>>val[a];
        cin>>m;
        for(ll i=1;i<=m;i++)
        {
            cin>>b;
            add(a,b);
            add(b,a);
        }
    }
    for(ll i=1;i<=n;i++)
    {
        dp[i][0]=INF;
    }
    dfs(1,-1);
    if(dp[1][0]==0) cout<<dp[1][1];
    else if(dp[1][1]==0) cout<<dp[1][0];
    else cout<<min(dp[1][1],dp[1][0]);
}
int main()
{    
    solve();
    return 0;
}

  • 22
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值