-
树形 DP。
设计状态 f ( i , 0 / 1 ) f(i,0/1) f(i,0/1) 表示选或不选 i i i 节点,覆盖 i i i 及其子树的最小花费。
状态转移:
{ f ( i , 0 ) = f ( i , 0 ) + f ( s o n i , 1 ) f ( i , 1 ) = f ( i , 1 ) + min ( f ( s o n i , 0 ) , f ( s o n i , 1 ) ) \begin{cases} f(i,0)=f(i,0)+f(son_i,1)\\ f(i,1)=f(i,1)+\min(f(son_i,0),f(son_i,1)) \end{cases} {f(i,0)=f(i,0)+f(soni,1)f(i,1)=f(i,1)+min(f(soni,0),f(soni,1))
注意看清题目中节点编号从 0 0 0 开始。#include <bits/stdc++.h> using namespace std; const int maxn=3005; struct edge{int to,nxt;}e[maxn]; int head[maxn],cnt,f[maxn][2]; void add(int x,int y){e[++cnt]={y,head[x]},head[x]=cnt;} void dfs(int x,int fa) { f[x][0]=0,f[x][1]=1; for(int i=head[x];i;i=e[i].nxt) { if(e[i].to==fa) continue; dfs(e[i].to,x); f[x][0]+=f[e[i].to][1],f[x][1]+=min(f[e[i].to][0],f[e[i].to][1]); } } int main() { int n;cin>>n; for(int i=1;i<=n;i++) { int ii,k,u;cin>>ii>>k; while(k--) cin>>u,add(ii+1,u+1),add(u+1,ii+1); } dfs(1,0); cout<<min(f[1][0],f[1][1]); return 0; }
P2016 战略游戏
于 2023-10-15 23:09:16 首次发布