HDU 4705 Y (树形DP)
题意 给定一棵树,计算数集{A,B,C}的个数,其中A,B,C是树上的节点,且不存在一条路径覆盖A,B,C。 思路 朴素的想法是枚举“Y”的中点,然后枚举三条树枝i,j,k,答案就是sigma(Si*Sj*Sk) = [( sigma(Si) )^3 - 3*sigma(Si)*sigma(Si^2) + 2*sigma(Si^3)] / 6,其中Si表示i子树上节点个数。但是这样太麻烦了。 我们考虑用 补集 来做。计算A,B,C被一条路径覆盖的个数。那么这样假设A<B<C,我们就可以枚举B,然后枚举两个树枝i,j,答案就是sigma(Si*Sj) =[ ( sigma(Si) )^2 - sigma ( Si^2 ) ] / 2,时间复杂度O(n)。 代码 [cpp] #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <string> #include <cstring> #include <vector> #include <set> #include <stack> #include <queue> #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) #define REP(i,