[CEOI2007] 树的匹配Treasury
类型:树形 DP
传送门:>Here<
题意:给一棵树,你可以匹配有边相连的两个点,问你这棵树的最大匹配是多少,并且计算出有多少种最大匹配。
解题思路
首先树形Dp是很明显的,$f[i][0]$表示$i$的子树中,$i$不参与匹配的最大匹配数,同样$f[i][1]$表示$i$参与匹配的最大匹配数。这样第一个子问题的答案就是$Max(f[1][0], f[1][1])$。
对于$f[i][0]$的转移很简单,既然$i$不参与匹配,那么$f[i][0]$就是它的每棵子树的最大匹配之和$$f[i][0]=\sum\limits_{ \ }Max(f[v][0],f[v][1])$$
对于$f[i][1]$,情况稍稍复杂一点。由于$i$节点最多只能被匹配一次,所以我们可以这样来考虑。对于节点$u$,选择其中一个子节点$v$来和自己匹配,剩余的仍然取最大值,这样剩余的最大值很显然是$f[u][0]-Max(f[v][0],f[v][1])$(刚才是用$Max(f[v][0],f[v][1])$推过来的),并且除了子节点$v$,$v$的其余儿子依然是独立的,所以再加上$f[v][0]$。所以转移方程即为$$f[u][1] = Max\{ f[u][0]-Max(f[v][0],f[v][1])+f[v][0]+1 \}$$
然后考虑第二个子问题,方案数怎么办?依然Dp。$g[i][k]$表示对应的$f[i][k]$的方案数。但注意了,答案不是$g[1][1]$,因为有可能$f[1][0]=f[1][1]$,这时候最大值有两个,所以答案可能是$g[1][0]+g[1][1]$。
还是先考虑$g[i][0]$如何转移,对于节点$u$,它由于是由各个子节点转移过来的,所以总的方案数就是各个子节点最大值方案数的积。还是一样,需要特判一下$g[v][0] =g[v][1]$的情况。
最难的也就是$g[i][1]$的转移了。对于这种情况,首先我们需要判断一下哪些节点与根匹配以后会转移出来最大值$f[u][1]$,而判断这个只需要按照前面的方程再推一遍看看是否相等就可以了。即$if(f[u][0]-Max(f[v][0],f[v][1])+f[v][0]+1 == f[u][1])$. 而这时候,我们还是仿照前面的思维过程,但是注意方案数中除去一部分使用除法而不是减法(前面是由乘法转移过来的),加上也要改成乘上。并且还是要特判$f[v][0]=f[v][1]的情况$。具体见代码。
想出上面这些并不复杂,而我却在$g$的初始化上卡了将近一小时。一开始我把每个$g[i][0]$和$g[i][1]$都初始化为$1$,结果挂了。调试千百遍之后把$g[i][1]$的初始化删掉以后突然就对了。这个现在我是这样理解的,因为我的$g[i][0]$是要拿去直接乘的,显然不能先赋成$0$,不然推出来的$g[i][0]$就全是$0$了。并且$g[i][1]$是加的,刚开始如果就是$1$就会影响结果。这个只不过是一个非常牵强的理解……
Code
高精度
/*written by -=qxz=- */ #include <cstdio> #include <cctype> #include <cstring> #include <vector> #include <algorithm> #include <cassert> #include <iostream> #include <string> #define INF (0x3f3f3f3f) #define Max(a,b) ((a) > (b) ? (a) : (b)) #define Min(a,b) ((a) < (b) ? (a) : (b)) #define N (1010) typedef long long ll; using namespace std; struct BigInteger { typedef unsigned long long ll; ; ; vector<int> s; BigInteger& clean(){)s.pop_back(); return *this;} BigInteger(ll num = ) {*this = num;} BigInteger(string s) {*this = s;} BigInteger& operator = (long long num) { s.clear(); do { s.push_back(num % BASE); num /= BASE; } ); return *this; } BigInteger& operator = (const string& str) { s.clear(); ) / WIDTH + ; ; i < len; i++) { int end = str.length() - i*WIDTH; , end - WIDTH); sscanf(str.substr(start,end-start).c_str(), "%d", &x); s.push_back(x); } return (*this).clean(); } BigInteger operator + (const BigInteger& b) const { BigInteger c; c.s.clear(); , g = ; ; i++) { && i >= s.size() && i >= b.s.size()) break; int x = g; if (i < s.size()) x += s[i]; if (i < b.s.size()) x += b.s[i]; c.s.push_back(x % BASE); g = x / BASE; } return c; } BigInteger operator - (const BigInteger& b) const { assert(b <= *this); BigInteger c; c.s.clear(); , g = ; ; i++) { && i >= s.size() && i >= b.s.size()) break; int x = s[i] + g; if (i < b.s.size()) x -= b.s[i]; ) {g = -; x += BASE;} ; c.s.push_back(x); } return c.clean(); } BigInteger operator * (const BigInteger& b) const { int i, j; ll g; vector<ll> v(s.size()+b.s.size(), ); BigInteger c; c.s.clear(); ;i<s.size();i++) ;j<b.s.size();j++) v[i+j]+=ll(s[i])*b.s[j]; , g = ; ; i++) { && i >= v.size()) break; ll x = v[i] + g; c.s.push_back(x % BASE); g = x / BASE; } return c.clean(); } BigInteger operator / (const BigInteger& b) const { assert(b > ); BigInteger c = *this; BigInteger m; ; i >= ; i--) { m = m*BASE + s[i]; c.s[i] = bsearch(b, m); m -= b*c.s[i]; } return c.clean(); } BigInteger operator % (const BigInteger& b) const { BigInteger c = *this; BigInteger m; ; i >= ; i--) { m = m*BASE + s[i]; c.s[i] = bsearch(b, m); m -= b*c.s[i]; } return m; } int bsearch(const BigInteger& b, const BigInteger& m) const{ , R = BASE-, x; ) { x = (L+R)>>; )>m) return x; else L = x;} else R = x; } } BigInteger& operator += (const BigInteger& b) {*this = *this + b; return *this;} BigInteger& operator -= (const BigInteger& b) {*this = *this - b; return *this;} BigInteger& operator *= (const BigInteger& b) {*this = *this * b; return *this;} BigInteger& operator /= (const BigInteger& b) {*this = *this / b; return *this;} BigInteger& operator %= (const BigInteger& b) {*this = *this % b; return *this;} BigInteger& ; return *this;} BigInteger& ; return *this;} bool operator < (const BigInteger& b) const { if (s.size() != b.s.size()) return s.size() < b.s.size(); ; i >= ; i--) if (s[i] != b.s[i]) return s[i] < b.s[i]; return false; } bool operator >(const BigInteger& b) const{return b < *this;} bool operator<=(const BigInteger& b) const{return !(b < *this);} bool operator>=(const BigInteger& b) const{return !(*this < b);} bool operator!=(const BigInteger& b) const{return b < *this || *this < b;} bool operator==(const BigInteger& b) const{return !(b < *this) && !(b > *this);} }; ostream& operator << (ostream& out, const BigInteger& x) { out << x.s.back(); ; i >= ; i--) { ]; sprintf(buf, "%08d", x.s[i]); ; j < strlen(buf); j++) out << buf[j]; } return out; } istream& operator >> (istream& in, BigInteger& x) { string s; if (!(in >> s)) return in; x = s; return in; } template <class T> inline void read(T &x){ , ch = ; x = ; ; ) + (x<<) + ch - '; if(f) x = -x; } int n,u,m,v; vector <int> G[N]; ]; BigInteger g[N][]; inline void AddEdge(int u, int v){ G[u].push_back(v); } void DP(int u, int fa){ ; ; i < sz; ++i){ if(G[u][i] == fa) continue; ++not_leaf; } g[u][] = ; if(!not_leaf){ return; } ; i < sz; ++i){ v = G[u][i]; if(v == fa) continue; DP(v,u); f[u][] += Max(f[v][], f[v][]); ] == f[v][]) g[u][] *= (g[v][] + g[v][]); else{ ] > f[v][]) g[u][] *= g[v][]; ] > f[v][]) g[u][] *= g[v][]; } } f[u][] = f[u][]; ; i < sz; ++i){ v = G[u][i]; if(v == fa) continue; f[u][] = Max(f[u][], f[u][]-Max(f[v][],f[v][])+f[v][]+); } ; i < sz; ++i){ v = G[u][i]; if(v == fa) continue; ]-Max(f[v][],f[v][])+f[v][]+ == f[u][]){ ] == f[v][] && g[v][]+g[v][] != ){ g[u][] += g[u][]/(g[v][]+g[v][])*g[v][]; } else{ ] > f[v][] && g[v][] != ){ g[u][] += g[u][]/(g[v][])*g[v][]; } ] > f[v][] && g[v][] != ){ g[u][] += g[u][]/(g[v][])*g[v][]; } } } } } int main(){ // freopen(".in","r",stdin); read(n); ; i <= n; ++i){ read(u); read(m); ; j <= m; ++j){ read(v); AddEdge(u,v); } } DP(,); printf(][], f[][])); ][] == f[][]) cout << g[][]+g[][]; else{ ][] > f[][]) cout << g[][]; ][] > f[][]) cout << g[][]; } ; }
[CEOI2007] 树的匹配Treasury的更多相关文章
- luogu P1623 [CEOI2007]树的匹配Treasury
题目链接 luogu P1623 [CEOI2007]树的匹配Treasury 题解 f[i][0/1]表示当前位置没用/用了 转移暴力就可以了 code // luogu-judger-enable ...
- [CEOI2007]树的匹配Treasury(树形DP+高精)
题意 给一棵树,你可以匹配有边相连的两个点,问你这棵树的最大匹配时多少,并且计算出有多少种最大匹配. N≤1000,其中40%的数据答案不超过 108 题解 显然的树形DP+高精. 这题是作为考试题考 ...
- bzoj5123 [Lydsy12月赛]线段树的匹配
题意: 线段树是这样一种数据结构:根节点表示区间 [1, n]:对于任意一个表示区间 [l, r] 的节点,若 l < r, 则取 mid = ⌊l+r/2⌋,该节点的左儿子为 [l, mid] ...
- 【bzoj5123】[Lydsy12月赛]线段树的匹配 树形dp+记忆化搜索
题目描述 求一棵 $[1,n]$ 的线段树的最大匹配数目与方案数. $n\le 10^{18}$ 题解 树形dp+记忆化搜索 设 $f[l][r]$ 表示根节点为 $[l,r]$ 的线段树,匹配选择根 ...
- CF308C-Sereja and Brackets-(线段树+括号匹配)
题意:给出一段括号,多次询问某个区间内能匹配多少括号. 题解:线段树,结构体三个属性,多余的左括号l,多余的右括号r,能够匹配的括号数val. 当前结点的val=左儿子的val+右儿子的val+min ...
- BZOJ5123 线段树的匹配(树形dp)
线段树的任意一棵子树都相当于节点数与该子树相同的线段树.于是假装在树形dp即可,记忆化搜索实现,有效状态数是logn级别的. #include<iostream> #include< ...
- bzoj千题计划164:bzoj5123: 线段树的匹配
http://www.lydsy.com/JudgeOnline/upload/201712/prob12.pdf dp[len][0/1] 表示节点表示区间长度为len,节点选/不选的 最大匹配 s ...
- bzoj 5123: [Lydsy1712月赛]线段树的匹配
设f[0/1][x]为区间[1,x]的根向下 不选(0)或者选(1) 的dp pair<最优值,方案数>. 可以很容易的发现总状态数就是log级别的,因为2*n 与 (2*n+1 或者 ...
- Linux DTS(Device Tree Source)设备树详解之二(dts匹配及发挥作用的流程篇)【转】
转自:https://blog.csdn.net/radianceblau/article/details/74722395 版权声明:本文为博主原创文章,未经博主允许不得转载.如本文对您有帮助,欢迎 ...
随机推荐
- [蛙蛙推荐]SICP第一章学习笔记-编程入门
本书简介 <计算机程序的构造与解释>这本书是MIT计算机科学学科的入门课程, 大部分学生在学这门课程前都没有接触过程序设计,也就是说这本书是针对编程新手写的. 虽然是入门课程,但起点比较高 ...
- python代码风格指南:pep8 中文版
本文档所提供的编码规范,适用于主要的Python发行版中组成标准库的Python代码.请参阅PEP关于Python的C实现的C编码风格指南的描述. 本文档和PEP257(文档字符串规范)改编自Guid ...
- c++入门之初话指针
先上代码:再进行总结知识: # include "iostream" struct ant_year_end { int year; }; int main() { using n ...
- FreeBSD常用操作
导读 最近遇到一些FreeBSD的故障,在这种操作系统上我们平时用的一些命令无法执行,FreeBSD的一些配置文件也和其他很多Linux系统不一样.为了方便以后查阅,我特别整理了这篇文档. 1. 网络 ...
- servlet程序HTTP Status 500 - Error instantiating servlet class 解决
在eclipase 中编译 servlet 但是一致报 HTTP Status 500 - Error instantiating servlet class XXX类 的问题 , 解决方法 1. ...
- java问题
Collection 和 Collections的区别? Collection是集合类的上级接口,继承与他的接口主要有Set 和List. Collections是针对集合类的一个帮助类,他提供一系列 ...
- 06_Hadoop分布式文件系统HDFS架构讲解
mr 计算框架 假如有三台机器 统领者master 01 02 03 每台机器都有过滤的应用程序 移动数据 01机== 300M >mr 移动计算 java程序传递给各个机器(mr) ...
- marMariaDB & MYSQL flexviews
Using Flexviews - part one, introduction to materialized views - Percona Database Performance Bloght ...
- FAIL - Deploy Upload Failed, Exception: [org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (112503036) exceeds the configured
Message: FAIL - Deploy Upload Failed, Exception: [org.apache.tomcat.util.http.fileupload.FileUpload ...
- select into赋值方式
declare v_price ,);--单价 v_usenum number;--水费字数 v_usenum2 number;--使用吨数 begin v_price:=2.45;--每吨单价 -- ...