一道简单的树形dp
动态转移方程:dp[root][1]+=min(dp[id][1],dp[id][0])
dp[root][0]+=dp[root][1]
若根节点放哨兵,则它的孩子节点有两种选择,若不放,呢么他的孩子节点只有一种选择
AC代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=2e3+5;
vector<int>vec[maxn];
int dp[maxn][2];//两种状态
int vis[maxn];//判断根节点
int n;
void dfs(int root)
{
dp[root][0]=0;
dp[root][1]=1;
for(int i=0;i<vec[root].size();i++)
{
int id=vec[root][i];
dfs(id);
dp[root][1]+=min(dp[id][1],dp[id][0]);
dp[root][0]+=dp[id][1];
}
}
int main()
{
while(~scanf("%d",&n))
{
memset(vis,0,sizeof(vis));
memset(vec,0,sizeof(vec));
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
{
int u,m,v;
scanf("%d:(%d)",&u,&m);
while(m--)
{
scanf("%d",&v);
vis[v]=1;
vec[u].push_back(v);
}
}
int root;
for(int i=0;i<n;i++)
{
if(!vis[i])
{
root=i;
break;
}
}
dfs(root);
printf("%d\n",min(dp[root][0],dp[root][1]));
}
}