hihocoder1243
描述
王先生抢走了MX班里的妹子。为了报复,MX决定炸毁王先生的城市。
城市可以看成是一棵n个结点的无根树。MX需要炸毁树上的每一条边,但是同一条边仅能被炸一次。
MX可选用的轰炸操作有两种:
1.选定两个结点u,v,并将从u到v的最短路径上的每一条边都炸毁。(如果路径上已经有被炸毁的边,则不能进行这次操作)
2.选定一个结点u,并将与u直接相连的每一条边都炸毁。(如果与u直接相连的已经有被炸毁的边,则不能进行这次操作)
请求出完成任务所需要的最少总操作次数。
简述就是通过最少的方式覆盖完所有的边,且边只能被覆盖一次~~
很明显的树形DP
dp[i][0/1]:=第i个点没有/有进行第二个操作,且全部覆盖了以i为根的子树的最少操作数
flag[i]:=第i个点没有进行第二个操作且孩子里面有flag[i]个没有进行第二个操作的数量
dp[i][0/1]:=第i个点没有/有进行第二个操作,且全部覆盖了以i为根的子树的最少操作数
flag[i]:=第i个点没有进行第二个操作且孩子里面有flag[i]个没有进行第二个操作的数量
如果flag[v]为奇数,那么u->v这条边可以合并到v的路径内~~~~
状态转移:
dp[u][1]=∑dp[v][0];
if(dp[v][1]
题解里面提到还应该对flag[v]奇偶性进行讨论,其实不用,显然dp[v][1]==dp[v][0]+((flag[v]+1)%2)的话取后者最优,因为可以合并,即减去flag[u]/2
那么到底应不应该分开讨论flag[v]的奇偶性,也不用,这个奇偶性只会对更新父亲的dp[u][0]有影响
那么还原dp[u][0]+=dp[v][0]-flag[v]/2+(flag[v]+1)%2; 注这里的dp[v][0]没有进行式子1
-flag[v]/2+(flag[v]+1)%2随着flag的增大变小,与奇偶性无关,所以只要确保flag[u]越来越大就好
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include