[SDOI2006]保安站岗

本文介绍了一种使用树形动态规划(DP)解决特定问题的方法,通过为每个节点存储三种状态来实现:未受保护、受保护和自我保护。文章包含了一个具体的C++实现示例,适用于解决具有1500个节点规模的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对每个节点存三个状态:未保护(但子树完全保证符合);被保护;自己站一个警察。

然后就好了

n才1500让我开始想到别的地方去了QAQ

(TMD)INF比-1好用到不知道哪里去了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(j,k,l) for (long long j=k;j<=l;++j)
#define red(j,k,l) for (long long j=k;j>=l;--j)
#define N 1505
#define inf 100000009

using namespace std;
long long n,cnt,a[N],pi[N],dp[N][3],st[N],ne[2*N],to[2*N];

void add(long long k,long long l){
	
	to[++cnt]=l;
	ne[cnt]=st[k];
	st[k]=cnt;
	
}

long long min(long long a,long long b){
	
	return (((a)>(b))?(b):(a));
	
}

void Dp(long long k){
	
	if (st[k]==0){
		
		dp[k][0]=0;		//未保护
		dp[k][1]=inf;	//被保护
		dp[k][2]=a[k];	//自己选
		return;
		
	}
	dp[k][0]=0,dp[k][1]=0,dp[k][2]=a[k];
	long long mxm=inf;
	for (long long i=st[k];i;i=ne[i]){
		
		Dp(to[i]);
		dp[k][0]+=dp[to[i]][1];
		dp[k][1]+=min(dp[to[i]][1],dp[to[i]][2]);
		dp[k][2]+=min(min(dp[to[i]][0],dp[to[i]][1]),dp[to[i]][2]);
		mxm=min(mxm,dp[to[i]][2]-dp[to[i]][1]);
		
	}
	if (mxm>0) dp[k][1]+=mxm;
	return;
	
}

int main(){
	
	scanf("%lld",&n);
	rep(i,1,n){
		
		long long k,l;
		scanf("%lld",&k);
		scanf("%lld%lld",a+k,&l);
		rep(j,1,l){
			
			long long p;
			scanf("%lld",&p);
			add(k,p);pi[p]++;
			
		}
		
	}
	long long rt=0;
	rep(i,1,n) if (pi[i]==0) rt=i;
	Dp(rt);
	printf("%lld\n",min(dp[rt][1],dp[rt][2]));
	system("pause");
	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值