题目链接
https://www.luogu.org/problemnew/show/UVA1292
分析
这不跟没有刘醒上司的舞会一样的套路么,怎么一个普及+,一个提高+.也是挺服luogu评分
$f[now][1/0]$表示取/不取$now$在$now$为根的子树中的最大值
转移照样简单
$f[now][0]=\sum max(f[son][0],f[son][1]) $,$son$是$now$的儿子节点
$f[now][1]= \sum f[son][0]+ 1$
当然我们先要找出个入度为0的点钦定为根
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cctype> #include <iostream> #include <queue> #define ll long long #define ri register int using std::min; using std::max; template <class T>inline void read(T &x){ x=0;int ne=0;char c; while(!isdigit(c=getchar()))ne=c=='-'; x=c-48; while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48; x=ne?-x:x;return; } const int maxn=2505; const int inf=0x7fffffff; struct Edge{ int ne,to; }edge[maxn<<1]; int h[maxn],num_edge=0; inline void add_edge(int f,int to){ edge[++num_edge].ne=h[f]; edge[num_edge].to=to; h[f]=num_edge; } int n,f[maxn][2]; int deg[maxn],root; void dfs(int now){ f[now][0]=0; f[now][1]=1; int v; for(ri i=h[now];i;i=edge[i].ne){ v=edge[i].to; dfs(v); f[now][0]+=f[v][1]; f[now][1]+=min(f[v][1],f[v][0]); } return ; } int main(){ int x,y,s; while(scanf("%d",&n)!=EOF){ num_edge=0; memset(deg,0,sizeof(deg)); memset(h,0,sizeof(h)); for(ri i=1;i<=n;i++){ scanf("%d:(%d)",&x,&y);x++; for(ri j=1;j<=y;j++){ read(s);s++; add_edge(x,s); deg[s]++; } } for(ri i=1;i<=n+1;i++)if(!deg[i]){root=i;break;} dfs(root); printf("%d\n",min(f[root][1],f[root][0])); } return 0; }
|