[CEOI2007]树的匹配Treasury(树形DP+高精)
题意
给一棵树,你可以匹配有边相连的两个点,问你这棵树的最大匹配时多少,并且计算出有多少种最大匹配。
N≤1000,其中40%的数据答案不超过 108
题解
显然的树形DP+高精。
这题是作为考试题考的,因为记得有一次考试,状态用两个数组存。
所以看到这题瞬间想到状态dp[i][0/1]代表以i为根的子树不选/选i点的最大匹配数。
f[i][0/1]代表以i为根的子树中不选/选i形成最大匹配的方案数。
然后方程改了半天:而且极长所以看代码吧。
TM还要加高精。。。
(第一个点挂了,特判过的)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const long long N=;
long long dp[N][],cnt,head[N],sum1[N],sum[N],n;
struct num{
long long a[],l;
}z,f[N][];
num add(num a,num b){
if(a.l<b.l)swap(a,b);
for(long long i=;i<=b.l;i++){
a.a[i]+=b.a[i];
}
for(long long i=;i<=a.l;i++)
if(a.a[i]>=){
a.a[i+]+=;
a.a[i]-=;
if(i==a.l)a.l++;
}
return a;
}
num mul(num a,num b,num c){
for(long long i=;i<=a.l;i++)
for(long long j=;j<=b.l;j++){
c.a[i+j-]+=a.a[i]*b.a[j];
}
long long top=;
for(long long i=;i<=a.l+b.l;i++){
if(c.a[i])top=i;
c.a[top+]+=c.a[top]/;
c.a[top]%=;
}
c.l=top;
return c;
}
struct edge{
long long to,nxt;
}e[N*];
void add(long long u,long long v){
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void getdp(long long u,long long fa){
long long sum=;
long long tmp=;
num tmpp;
tmpp.a[]=;
tmpp.l=;
for(long long i=head[u];i;i=e[i].nxt){
long long v=e[i].to;
if(v==fa)continue;
getdp(v,u);
sum+=dp[v][];
if(dp[v][]==dp[v][]&&dp[v][])tmpp=mul(tmpp,add(f[v][],f[v][]),z);
else tmpp=mul(tmpp,f[v][],z);
}
dp[u][]=sum;
f[u][]=tmpp;
tmp=;
tmpp.a[]=;
tmpp.l=;
for(long long i=head[u];i;i=e[i].nxt){
long long v=e[i].to;
if(v==fa)continue;
if(sum-dp[v][]+dp[v][]+==tmp){
num tmppp=f[v][];
for(long long j=head[u];j;j=e[j].nxt){
long long vv=e[j].to;
if(vv==fa||v==vv)continue;
if(dp[vv][]==dp[vv][]&&dp[vv][])tmppp=mul(tmppp,add(f[vv][],f[vv][]),z);
else tmppp=mul(tmppp,f[vv][],z);
}
tmpp=add(tmpp,tmppp);
}
if(sum-dp[v][]+dp[v][]+>tmp){
tmp=sum-dp[v][]+dp[v][]+;
tmpp=f[v][];
for(long long j=head[u];j;j=e[j].nxt){
long long vv=e[j].to;
if(vv==fa||v==vv)continue;
if(dp[vv][]==dp[vv][]&&dp[vv][])tmpp=mul(tmpp,add(f[vv][],f[vv][]),z);
else tmpp=mul(tmpp,f[vv][],z);
}
}
}
dp[u][]=tmp;
f[u][]=tmpp;
}
void write(num x){
if(x.l==&&x.a[]==){
cout<<;
return;
}
for(long long i=x.l;i>=;i--){
printf("%lld",x.a[i]);
}
}
int main(){
scanf("%lld",&n);
for(long long i=;i<=n;i++){
long long m,u;
scanf("%lld%lld",&u,&m);
for(long long j=;j<=m;j++){
long long a;
scanf("%lld",&a);
add(u,a);add(a,u);
}
}
getdp(,);
if(dp[][]>dp[][]){
printf("%lld\n",dp[][]);
write(f[][]);
}
else if(dp[][]<dp[][]){
printf("%lld\n",dp[][]);
write(f[][]);
}
else {
printf("%lld\n",dp[][]);
write(add(f[][],f[][]));
}
return ;
}
[CEOI2007]树的匹配Treasury(树形DP+高精)的更多相关文章
- luogu P1623 [CEOI2007]树的匹配Treasury
题目链接 luogu P1623 [CEOI2007]树的匹配Treasury 题解 f[i][0/1]表示当前位置没用/用了 转移暴力就可以了 code // luogu-judger-enable ...
- [CEOI2007] 树的匹配Treasury
类型:树形 DP 传送门:>Here< 题意:给一棵树,你可以匹配有边相连的两个点,问你这棵树的最大匹配是多少,并且计算出有多少种最大匹配. 解题思路 首先树形Dp是很明显的,$f[i][ ...
- BZOJ5123 线段树的匹配(树形dp)
线段树的任意一棵子树都相当于节点数与该子树相同的线段树.于是假装在树形dp即可,记忆化搜索实现,有效状态数是logn级别的. #include<iostream> #include< ...
- 洛谷P4608 [FJOI2016]所有公共子序列问题 【序列自动机 + dp + 高精】
题目链接 洛谷P4608 题解 建个序列自动机后 第一问暴搜 第二问dp + 高精 设\(f[i][j]\)为两个序列自动机分别走到\(i\)和\(j\)节点的方案数,答案就是\(f[0][0]\) ...
- 1113: [视频]树形动态规划(TreeDP)8:树(tree)(树形dp状态设计总结)
根据最近做的几道树形dp题总结一下规律.(从这篇往前到洛谷 P1352 ) 这几道题都是在一颗树上,然后要让整棵树的节点或边 满足一种状态.然后点可以影响到相邻点的这种状态 然后求最小次数 那么要从两 ...
- poj3107(树的重心,树形dp)
题目链接:https://vjudge.net/problem/POJ-3107 题意:求树的可能的重心,升序输出. 思路:因为学树形dp之前学过点分治了,而点分治的前提是求树的重心,所以这题就简单水 ...
- BZOJ1089 [SCOI2003]严格n元树 【dp + 高精】
Description 如果一棵树的所有非叶节点都恰好有n个儿子,那么我们称它为严格n元树.如果该树中最底层的节点深度为d (根的深度为0),那么我们称它为一棵深度为d的严格n元树.例如,深度为2的严 ...
- 【bzoj1907】树的路径覆盖 树形dp
题目描述 输入 输出 样例输入 1 7 1 2 2 3 2 4 4 6 5 6 6 7 样例输出 3 题解 树形dp 设f[x]表示以x为根的子树完成路径覆盖,且x为某条路径的一端(可以向上延伸)的最 ...
- bzoj 1089: [SCOI2003]严格n元树【dp+高精】
设f[i]为深度为i的n元树数目,s为f的前缀和 s[i]=s[i-1]^n+1,就是增加一个根,然后在下面挂n个子树,每个子树都有s[i-1]种 写个高精就行了,好久没写WA了好几次-- #incl ...
随机推荐
- Photoshop CC (2015.5) 2016.6 版已发布
Photoshop CC (2015.5) 2016.6 版已发布 adobe-cc-no-more-direct-download-links.html 不再有直接下载的升级包了,不开心 :( 下载 ...
- 《鸟哥的Linux私房菜》笔记——01. 计算机概论
计算机的五大部分:输入单元.输出单元.CPU(控制单元(Control Unit).算数逻辑单元(ALU)).内存. CPU 的架构 精简指令集(Reduced Instruction Set Com ...
- img标签IE下有边距——2017/7/21
设置css 在全局变量的是和给img标签设置 img{ border:0;} 1,img{float:left}2,img{display:block}
- Comparator 与 Comparable
转载自 http://www.cnblogs.com/sunflower627/p/3158042.html 1. Comparator 和 Comparable 相同的地方 他们都是java的一个接 ...
- indexedDB介绍
什么是 indexedDB IndexedDB 是一种使用浏览器存储大量数据的方法.它创造的数据可以被查询,并且可以离线使用. IndexedDB对于那些需要存储大量数据,或者是需要离线使用的程序是非 ...
- root of factory hierarchy
项目编译错误! project---->clean
- django 开发之给admin 模块添加富文本编辑器
第一步下载kindeditor http://kindeditor.net/demo.php 下载下来后放到静态文件static 下面的js下面 接着在admin 模块文章类下引入这富文本编辑器: ...
- 成长日记--记录在WB的第一个项目。
具体为什么跑去外包,只能说自己太水了,或者太懒了,都不好好投简历,也没入这个坑过,如果有想去外包的,除非钱给到市场价的1.5倍以上,否则别考虑了. 项目是国内第一做通信公司的,从具体的需求说起比较好, ...
- 红黑树(RBTREE)之上-------构造红黑树
该怎么说呢,现在写代码的速度还是很快的,很高兴,o(^▽^)o. 光棍节到了,早上没忍住,手贱了一般,看到*D的优惠,买了个机械键盘,晚上就到了,敲着还是很舒服的,和老婆炫耀了一把哈哈. 光棍节再去* ...
- 现代C++
C++ 是世界上最常用的编程语言之一. 编写良好的 C++ 程序是快速.高效的. 该语言比其他语言更加灵活,因为你可以使用它来创建各种应用,包括有趣刺激的游戏.高性能科学软件.设备驱动程序.嵌入式程序 ...