题目 题意: n个点的有根树,每个点有权值ai。选了父节点就不能选择子节点,并且最多选择m个节点。 思路: f[i][j][0/1]:以i为根,至多选择j个节点,0:选,1:不选。 参考上一题的什么背包,枚举树根i选择的节点个数j,之后枚举子树选择的节点0,1…j。如果不选树根i,那么子树都可以选;如果选树根i,只能不选子树的根节点。 这里有点费解的是不知道为啥j要从大到小枚举,wls的解释是因为该题的模型和上一题背包一样,所以照搬从大到小。 以后最后赋值的循环来看,如果从小到大会导致一个点会选择多次,每个i都能被i-1更新,i=1时正是选择它自己,i=2又能再选一次自己,寄。同样,递推方程时也有点这个意思,会重复计算的,学不明白了。 时间复杂度: O(nmm) 代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define OldTomato ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
#define fir(i,a,b) for(int i=a;in>>m;
for(int i=2;i>x;va[x].push_back(i);}
for(int i=1;i>a[i];
dfs(1);
coutT;
// read(T);
while(T--)
{
solve();
}
return 0;
}