[SDOI2006]保安站岗 树dp

要记录三种状态:

1、被子节点覆盖

2、等待父节点覆盖

3、建立覆盖节点

然后转移就好了,有一点麻烦的就是被子节点覆盖,需要保证至少有一个子节点建立

注:检查变量名与实际含义。


码:

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int f[1505][4],k[1505],o,m,n,i,j,x,fu[1505];
vector<int>v[1505];
void dfs(int o)
{
	int i,nd,min1=999999999,min2=0;
	f[o][1]=k[o];
	for(i=0;i<v[o].size();i++)
	{
		nd=v[o][i];
		dfs(nd);
		f[o][1]+=min(f[nd][0],min(f[nd][1],f[nd][2]));//建在这里 
		  if(f[nd][1]-f[nd][2]<min1)min1=f[nd][1]-f[nd][2],min2=nd;     //影响到这里
		f[o][0]+=min(f[nd][2],f[nd][1]);// 		
	}	
	if(v[o].size()==0)
	{
	f[o][2]=999999999;	
return ;
}
	f[o][2]+=f[min2][1];
	for(i=0;i<v[o].size();i++)
	{
		nd=v[o][i];
	if(nd==min2)continue;
	f[o][2]+=min(f[nd][1],f[nd][2]);		
	}	
}
int main()
{
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%d%d%d",&o,&x,&m);
		k[o]=x;
		for(j=1;j<=m;j++)
		{
			scanf("%d",&x);
			v[o].push_back(x);
			fu[x]=o;		
		}		
	}
	for(i=1;i<=n;i++)
	if(fu[i]==0)
	{
		o=i;
		break;
	}
dfs(o);	
printf("%d",min(f[o][1],f[o][2]));
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值