博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 6091 - Rikka with Match
阅读量:5022 次
发布时间:2019-06-12

本文共 1382 字,大约阅读时间需要 4 分钟。

 思路

树形dp,设计状态如下:

 

设 $dp_u_i_0$表示 以点 u 为根的子树 最大匹配数模 m 为 i 时,且 u 点没有匹配的方案数

DP[u][i][1] 表示 以点 u 为根的子树 最大匹配数模 m 为 i 时,且 u 点匹配上的方案数
递推公式如下:
DP[u][k][0](不匹配该节点) +=
  ∑ [i+j==k] 2 * DP[u][i][0] * DP[v][j][1](此时u->v这条边连不连都不会影响到匹配集,所以*2) +
  DP[u][i][0] * DP[v][j][0](儿子已近匹配了)
DP[u][k][1](该节点已经连了边) +=
   ∑ [i+j==k] 2 * DP[u][i][1] * ( DP[v][j][0] + DP[v][j][1] )
DP[u][k][1] (该节点现在正要连边)+=
  ∑ [i+j==k-1(预留出一个位用于匹配)] DP[u][i][0] * DP[v][j][0](此时这条边必须存在并且u,v都不能匹配别的边)
参考自

代码

#include
#include
#include
#include
using namespace std;#define int long long#define mod 998244353#define N 50001#define M 410vector vec[N];int dp[N][M][2],size[N]/*记录节点能最多能匹配多少边*/,temp[M][2]/*dp数组在更新中途不能更改,故用此数组代替*/,m;void add(int u,int v)//使用边更新数组{ memset(temp,0,sizeof(temp)); for(int i=0;i<=size[u];i++)//这里时间复杂度可以证明为n*m { for(int j=0;j<=size[v];j++) { temp[i+j][0]+=2*dp[u][i][0]*dp[v][j][1]+dp[u][i][0]*dp[v][j][0]; temp[i+j][0]%=mod; temp[i+j][1]+=2*dp[u][i][1]*(dp[v][j][0]+dp[v][j][1]); temp[i+j][1]%=mod; temp[i+j+1][1]+=dp[u][i][0]*dp[v][j][0]; temp[i+j+1][1]%=mod; } } for(int i=0;i
>n>>m; for(int i=1;i

  

转载于:https://www.cnblogs.com/linzhuohang/p/11305427.html

你可能感兴趣的文章
设计模式のCompositePattern(组合模式)----结构模式
查看>>
二进制集合枚举子集
查看>>
磁盘管理
查看>>
SAS学习经验总结分享:篇二—input语句
查看>>
UIImage与UIColor互转
查看>>
RotateAnimation详解
查看>>
系统管理玩玩Windows Azure
查看>>
c#匿名方法
查看>>
如何判断链表是否有环
查看>>
【小程序】缓存
查看>>
ssh无密码登陆屌丝指南
查看>>
MySQL锁之三:MySQL的共享锁与排它锁编码演示
查看>>
docker常用命令详解
查看>>
jQuery技巧大放送
查看>>
字符串转换成JSON的三种方式
查看>>
Hive时间函数笔记
查看>>
clojure-emacs-autocomplete
查看>>
一个自己写的判断2个相同对象的属性值差异的工具类
查看>>
10 华电内部文档搜索系统 search03
查看>>
[HIHO1149]回文字符序列(dp)
查看>>