完美的集合(题解)

本文介绍了如何在树上统计特定集合的数量,利用点数-边数=1的性质简化问题,并讲解了DFS序转移技巧在解决树上背包问题中的应用。通过DFS序动态规划求解最大价值及完美集合数量,最后给出解决方案的时间复杂度分析。
摘要由CSDN通过智能技术生成

例题

完美的集合

技巧

点数-边数=1

现在如果你要在树上统计某种特定集合的数量,有一种比较简单的方法就是统计包括某个点的集合数量,加起来,减去包括某条边的集合,就可以得出最后的集合了。

DFS序转移

如果要求你在树上背包你打算怎么办,神犇就给出了一个很好的方法。

一个集合利用合并从下到上做背包是 O ( n 3 ) O(n^3) O(n3),但是遍历一个个点加入进来就是 O ( n 2 ) O(n^2) O(n2)了,但是关键是如何遍历。

先把DFS序(进入的顺序)做出来,然后倒着DFS队列DP,如果一个点 x x x选择自己的话,他就选择 + 1 +1 +1的位置,如果他不选择自己的话,那么他就直接继承 + s i z e [ x ] +size[x] +size[x]的位置,就可以了。

题解

学会了技巧,这道题目就简单多了,模数是 5 23 5^{23} 523,首先利用DFS序DP得到最大的价值,同时得到包括某个点的最大价值的集合数,用组合数取模(之前的同余系列)得到包括这个点的完美集合,最后减去包括某条边的完美集合即可。(当然在DFS序DP之前要先处理那些点能否到达,这样那个重量<=的条件好处理)

另外,最大价值的集合数最大大概为 2 60 2^{60} 260

时间复杂度: O ( n 2 m + 取 模 复 杂 度 ) O(n^2m+取模复杂度) O(n2m+)

代码

#include<bits/stdc++.h>
#define  S  23
#define  N  70
#define  NN  140
#define  LLp  pair<LL,LL>
using  namespace  std;
typedef  long  long  LL;
template  <class  T>
inline  T  mymax(T  x,T  y){
   return  x>y?x:y;}
template  <class  T>
inline  T  mymin(T  x,T  y){
   return  x<y?x:y;}
LL  mod=(LL)11920928955078125;
inline  LL  mul(LL  x,LL  y){
   return  (x*y-(LL)((long  double)x*y/mod+1e-10)*mod);}
inline  LL  pow(LL  x,LL  k)//求逆元专用 
{
   
	LL  ans=1;
	while(k)
	{
   
		if(k&1)ans=mul(x,ans);
		x=mul(x,x);k>>=1;
	}
	return  ans;
}
namespace  Big_num//大整数组合数 
{
   
	LL  pw[S]={
   1},C[S]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值