Desription
Sol
状态:
f[i][0]表示i不放士兵时,以i为根的子树所需要的最小士兵数
f[i][1]表示i放士兵时,以i为根的子树所需要的最小士兵数
转移:
f[i][0]:i不放,那么它的子结点都要放
f[i][1]:i放,那么它的子结点可放可不放,取小即可
感觉比较板子题QwQ
Code
(It was written long long ago.)
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 using namespace std; 5 int r() 6 { 7 int x=0,y=1;;char ch; 8 ch=getchar(); 9 while(ch<'0'||ch>'9') {if(ch=='-') y=-1;ch=getchar();} 10 while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 11 return x*y; 12 } 13 int n; 14 int num[1600]; 15 bool ff[1600]; 16 vector<int> son[1600]; 17 int root; 18 void read() 19 { 20 n=r(); 21 for(int i=0;i<n;i++) 22 { 23 i=r(); 24 num[i]=r(); 25 for(int j=1;j<=num[i];j++) 26 { 27 int x=r(); 28 son[i].push_back(x); 29 ff[x]=1; 30 } 31 } 32 while(ff[root]) root++; 33 } 34 int f[1600][2]; 35 void dp(int x) 36 { 37 f[x][0]=0; 38 f[x][1]=1; 39 if(num[x]==0) return ; 40 for(int i=0;i<num[x];i++) 41 { 42 int y=son[x][i];dp(y); 43 f[x][0]+=f[y][1]; 44 f[x][1]+=min(f[y][1],f[y][0]); 45 } 46 } 47 int main() 48 { 49 read(); 50 dp(root); 51 int ans=min(f[root][0],f[root][1]); 52 printf("%d",ans); 53 return 0; 54 }