https://www.luogu.org/problemnew/show/P2458
一开始想当然用两种状态dp[i][0]代表i不站人 dp[i][1]代表i站人。。 这样每隔一层必站一个人 肯定不对 当u的儿子v站人后 只通过两种状态不能完全体现v对u的监视作用 即u的父亲f不知道u是否还需要保护 只要u不站人就会觉得u需要保护 从而无法做出正确决定
比如下面这个样例
4
1 1 1 2
2 2 1 3
3 2 1 4
4 1 0
dp[i][0]代表i无人监视 dp[i][1]代表i被人监视 dp[i][2]代表i站人 这才是完整状态 解决了上述问题
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=0x3f3f3f3f;
const int maxn=2e3+10;
vector <int> edge[maxn];
int dp[maxn][3];
int val[maxn],book[maxn],pre[maxn],suf[maxn];
int n,root;
void dfs(int cur)
{
int i,v,flag,sum;
dp[cur][0]=0;//1
dp[cur][1]=N;//12
dp[cur][2]=val[cur];//012
for(i=0;i<edge[cur].size();i++){
v=edge[cur][i];
dfs(v);
}
flag=1;
for(i=0;i<edge[cur].size();i++){
v=edge[cur][i];
dp[cur][0]+=dp[v][1];
if(dp[v][1]==N) flag=0;
}
if(!flag) dp[cur][0]=N;
sum=0;
for(i=0;i<edge[cur].size();i++){
v=edge[cur][i];
sum+=min(dp[v][1],dp[v][2]);
}
for(i=0;i<edge[cur].size();i++){
v=edge[cur][i];
dp[cur][1]=min(dp[cur][1],sum-min(dp[v][1],dp[v][2])+dp[v][2]);
}
for(i=0;i<edge[cur].size();i++){
v=edge[cur][i];
dp[cur][2]+=min(dp[v][0],min(dp[v][1],dp[v][2]));
}
//printf("*%d %d %d %d*\n",cur,dp[cur][0],dp[cur][1],dp[cur][2]);
}
int main()
{
int i,k,u,v;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&u);
scanf("%d",&val[u]);
scanf("%d",&k);
while(k--){
scanf("%d",&v);
edge[u].pb(v);
book[v]=1;
}
}
for(i=1;i<=n;i++){
if(!book[i]) root=i;
}
dfs(root);
printf("%d\n",min(dp[root][1],dp[root][2]));
return 0;
}
/*
3
1 1 2 2 3
2 1000 0
3 1000 0
*/