题意是这样,有一个篮子里放有若干个石子,每次可以在树的一个叶节点上放一个石子,如果一个节点的所有儿子都被放上石子,则将其儿子上的所有石子放回到篮子中,在该节点上放上一个石子。问要使得根节点上有一个石子,篮子中开始至少有多少个石子。
这题是基于树的一个贪心,假设当前节点为i,其儿子节点k放入1石子至少需要篮子中初始石子的数量为num[k],则在当前节点放入一个石子的策略是先将num[k]最大的子节点先放置,然后求得k-1+num[k]的最大值即为当前节点的num值(k为第k个儿子节点)
代码如下
1 # include <cstdio>
2 # include <vector>
3 # include <iostream>
4 # include <algorithm>
5 using namespace std;
6 const int N=201;
7 int n;
8 vector<int> g[N];
9 int minnum[N];
10 bool cmp(const int &a,const int &b)
11 {
12 return minnum[a]>minnum[b];
13 }
14 void dfs(int pos)
15 {
16 if(g[pos].empty())
17 minnum[pos]=1;
18 else
19 {
20 for(int i=0;i<g[pos].size();i++)
21 dfs(g[pos][i]);
22 sort(g[pos].begin(),g[pos].end(),cmp);
23 int max=-1;
24 for(int i=0;i<g[pos].size();i++)
25 if(i+minnum[g[pos][i]]>max)
26 max=i+minnum[g[pos][i]];
27 minnum[pos]=max;
28 }
29 }
30 int main()
31 {
32 int testcase;
33 scanf("%d",&testcase);
34 while(testcase--)
35 {
36 scanf("%d",&n);
37 for(int i=1;i<=n;i++)
38 {
39 int num,pos;
40 scanf("%d %d",&pos,&num);
41 g[pos].clear();
42 while(num--)
43 {
44 int t;
45 scanf("%d",&t);
46 g[pos].push_back(t);
47 }
48 }
49 dfs(1);
50 printf("%d\n",minnum[1]);
51 }
52 //system("pause");
53 return 0;
54 }
55