我的第一题树形DP,比较简单
简单的讲下我的思路。仅表纪念
对于一个节点来说有可能的情况只有两个:一个是这个节点站守卫,那么它的孩子有两种情况,一种是孩子节点上也站守卫,另一种是孩子节点上不站守卫,然后取这两种情况当中的较小值;第二个这个节点上不站守卫,那么为了保证每条边都能被守卫到,那么它的孩子肯定是要站守卫的。
其中dp1表示出现第一个情况时该节点最少的守卫数量,dp2表示第二个情况时该节点最少的守卫数量,然后再取这两者中的较小值。
在main函数中注意一些小的处理
#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 1500;
struct node
{
int num;
int next[maxn];
}p[maxn];
int dp1[maxn],dp2[maxn];
int min(int a,int b)
{
return a < b? a:b;
}
int dp(int root)
{
dp1[root] = 1;
dp2[root] = 0;
for(int i = 0;i < p[root].num;i++)
{
int tmp = p[root].next[i];
dp(tmp);
dp2[root] += dp1[tmp];
dp1[root] += min(dp1[tmp],dp2[tmp]);
}
return min(dp1[root],dp2[root]);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(dp1,0,sizeof(dp1));
memset(dp2,0,sizeof(dp2));
int a,b,root;
for(int i = 0;i < n ;i++)
{
scanf("%d:(%d)",&a,&b);
p[a].num = b;
if(i==0)
root = a;
for(int j = 0;j<p[a].num;j++)
scanf("%d",&p[a].next[j]);
}
printf("%d\n",dp(root));
}
return 0;
}