传送门啦
战略游戏这个题和保安站岗很像,这个题更简单,这个题求的是士兵人数,而保安站岗需要求最优价值。
定义状态$ f[u][0/1] $ 表示 $ u $ 这个节点不放/放士兵
根据题意,如果当前节点不放置士兵,那么它的子节点必须全部放置士兵,因为要满足士兵可以看到所有的边,所以
$ f[u][0]+=f[v][1] $ ,其中$ v $ 是 $ u $ 的子节点
如果当前节点放置士兵,它的子节点选不选已经不重要了(因为树形dp自下而上更新,上面的节点不需要考虑),所以
$ f[u][1]+=min(f[v][0],f[v][1]) $
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- using namespace std;
- const int maxn = 1505;
-
- inline int read(){
- char ch = getchar();
- int f = 1 , x = 0;
- while(ch > '9' || ch < '0'){if(ch == '-')f = -1; ch = getchar();}
- while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();}
- return x * f;
- }
-
- int n,flag,k,x;
- int head[maxn],tot;
- int f[maxn][5];
-
- struct Edge{
- int from,to,next;
- }edge[maxn << 1];
-
- void add(int u,int v){
- edge[++tot].from = u;
- edge[tot].to = v;
- edge[tot].next = head[u];
- head[u] = tot;
- }
-
- void dfs(int u,int fa) {
- f[u][1] = 1 , f[u][0] = 0;
- for(int i=head[u];i;i=edge[i].next) {
- int v = edge[i].to;
- if(v != fa) {
- dfs(v , u);
- f[u][0] += f[v][1];
- f[u][1] += min(f[v][1] , f[v][0]);
- }
- }
- }
-
- int main(){
- n = read();
- for(int i=0;i<=n-1;i++){
- flag = read(); k = read();
- if(k == 0)continue;
- for(int i=1;i<=k;i++){
- x = read();
- add(flag , x); add(x , flag);
- }
- }
- dfs(0 , -1);
- printf("%d\n",min(f[0][1] , f[0][0]));
- return 0;
- }