四叶草魔杖
这道题目作为枚举子集的题目见识一下
首先对于一个连通块,如果点权之和为\(0\),那么我们算出MST显然就是最优解
我们看一下数据范围,可能是考状态压缩
我们把状态\(i\)设出来后,可以先尝试考虑某一个点,但是你发现这样不太好考虑,而且只考虑这一个点的话,那么这个点所加入的连通块的点权之和为\(0\),然而没加入这个点之前这个连通块的点权之和一般就不为\(0\)了,难道我们还要再开一维记录信息吗?
显然不是,所以考虑方向不是考虑只加入一个点。由于我们要求连通块点权之和为\(0\),所以我们直接考虑某一个连通块,也就是枚举子集转移即可
当然如果用刷表法的话就不用枚举子集了
update 2024.7.24
先看数据范围,考虑状态压缩,不难设出状态\(f[i]\)表示所考虑的点集为\(i\)时,选出若干条边使得这些点能够通过传递能量来让每个点的能量都是\(0\)
然后考虑转移,尝试枚举每一条边,然而发现这样的话还要考虑每一条边传递的能量是多少,这显然无法承受,于是去考虑其他转移,这个时候就要读懂题目,题目说传递任何数量的能量的花费都一样,这就告诉我们如果一个连通块的权值和为\(0\),那么他就符合条件
这个时候也许会想,按照Kruscal的过程求出若干个权值和为\(0\)的连通块是不是就好了?其实不是的,反例见下
所以这个时候就要重新考虑状态压缩,按照一个连通块一个连通块地考虑,将当前状态提取出若干个点作为一个连通块,然后求出这个连通块的MST(没有的话设置为无穷大)进行转移即可
update 2024.9.5
这道题目也是DP题目子特征的一个体现,我们枚举\(i\)的时候也一定要让\(i\)
这个集合的总和为\(0\)