树形DP。
跟之前那个放灯的题很像,考虑每个点黑与白两种情况。涂白色的前提是子节点都是黑色。黑色可以由子节点的最小和转移而来。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN 1505
using namespace std;
vector<int> gl[MAXN];
int dp[MAXN][2];
bool vis[MAXN][2];
int n;
int solve(int u,int v)
{
if(vis[u][v]) return dp[u][v];
vis[u][v]=true;
dp[u][v]=0;
if(v==0)
{
for(int i=0; i<gl[u].size(); ++i)
dp[u][0]+=solve(gl[u][i],1);
return dp[u][0];
}
else if(v==1)
{
for(int i=0; i<gl[u].size(); ++i)
dp[u][1]+=min(solve(gl[u][i],0),solve(gl[u][i],1));
dp[u][1]++;
return dp[u][1];
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
int root;
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis));
for(int i=0; i<n; ++i)
{
int u,v,t;
scanf("%d:(%d)",&u,&v);
if(i==0) root=u;
gl[u].clear();
for(int j=0; j<v; ++j)
{
scanf("%d",&t);
gl[u].push_back(t);
}
}
printf("%d\n",min(solve(root,1),solve(root,0)));
}
return 0;
}