对每个节点存三个状态:未保护(但子树完全保证符合);被保护;自己站一个警察。
然后就好了
n才1500让我开始想到别的地方去了QAQ
(TMD)INF比-1好用到不知道哪里去了
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(j,k,l) for (long long j=k;j<=l;++j)
#define red(j,k,l) for (long long j=k;j>=l;--j)
#define N 1505
#define inf 100000009
using namespace std;
long long n,cnt,a[N],pi[N],dp[N][3],st[N],ne[2*N],to[2*N];
void add(long long k,long long l){
to[++cnt]=l;
ne[cnt]=st[k];
st[k]=cnt;
}
long long min(long long a,long long b){
return (((a)>(b))?(b):(a));
}
void Dp(long long k){
if (st[k]==0){
dp[k][0]=0; //未保护
dp[k][1]=inf; //被保护
dp[k][2]=a[k]; //自己选
return;
}
dp[k][0]=0,dp[k][1]=0,dp[k][2]=a[k];
long long mxm=inf;
for (long long i=st[k];i;i=ne[i]){
Dp(to[i]);
dp[k][0]+=dp[to[i]][1];
dp[k][1]+=min(dp[to[i]][1],dp[to[i]][2]);
dp[k][2]+=min(min(dp[to[i]][0],dp[to[i]][1]),dp[to[i]][2]);
mxm=min(mxm,dp[to[i]][2]-dp[to[i]][1]);
}
if (mxm>0) dp[k][1]+=mxm;
return;
}
int main(){
scanf("%lld",&n);
rep(i,1,n){
long long k,l;
scanf("%lld",&k);
scanf("%lld%lld",a+k,&l);
rep(j,1,l){
long long p;
scanf("%lld",&p);
add(k,p);pi[p]++;
}
}
long long rt=0;
rep(i,1,n) if (pi[i]==0) rt=i;
Dp(rt);
printf("%lld\n",min(dp[rt][1],dp[rt][2]));
system("pause");
}