UVA1292StrategicGame--树形DP

题目链接

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;
//printf("%d %d\n",now,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++;
//printf("%d %d\n",x,y);
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;
}