废话不想多说,代码上都有注释。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int p[1500],c[1500],dp[1500][2],sum[1500],m[1500],m2[1500],ji[1500];
//p[k]=t表示k的父节点为t,c[t]=s表示t的子节点数
//dp[i][0]表示节点i不取,dp[i][1]表示取节点i;
//sum,m,m2分别做节点更新时保存数组值用。
int min(const int a,const int b )
{
if(a<b)return a;
else return b;
}
int main()
{
freopen("t.txt","r",stdin);
int n,i,k,t,j,u,v,cur;
while(~scanf("%d",&n))
{
memset(p,-1,sizeof(p));
memset(dp,0,sizeof(dp));
memset(sum,0,sizeof(sum));
memset(m,0,sizeof(m));
memset(m2,0,sizeof(m2));
for(i=0;i<n;i++)
{
scanf("%d:(%d)",&u,&v);
c[u]=v;
for(k=0;k<v;k++)
{
scanf("%d",&t);
p[t]=u;
}
}
for(i=0;i<n;i++)
{
if(!c[i])
{
dp[i][0]=0;dp[i][1]=1;
cur=i;
while(p[cur]!=-1)
{ //若父节点取了,则子节点可取可不取。同时,更新节点时,为避免重复累加,引入另一数组保存之前的结果。
sum[p[cur]]=sum[p[cur]]-m[cur];
m[cur]=min(dp[cur][0],dp[cur][1]);
sum[p[cur]]+=m[cur];
dp[p[cur]][1]=sum[p[cur]]+1;
//若父节点不取,则子节点必取。
dp[p[cur]][0]-=m2[cur];
dp[p[cur]][0]+=dp[cur][1];
m2[cur]=dp[cur][1];
cur=p[cur];
}
}
}
while(p[cur]!=-1)cur=p[cur];
printf("%d\n",min(dp[cur][0],dp[cur][1]));
}
return 0;
}