神仙的容斥题与神仙的树形DP题。

首先搞一个指数级的做法:求总的、能够覆盖每一条边的方案数,通过容斥可以得到\(\text{ans}=\sum\limits_E{(-1)^{|E|}F(E)}\)。其中,\(F(E)\)表示钦定删除边集\(E\)后,其他的连边方案数。显然经过删边操作,这张图被划分成了很多联通块,联通块之间没有连边,方案数就是每个联通快的方案数的成绩。特别地,当\(|E|=0\)时,这个是总情况数。

如何求解一个联通块内的连边方案数呢?先上式子:\(\text{ret}=1 \times 3 \times 5 \times \cdots \times (n - 3) \times (n - 1)\)。如何理解这个式子呢?首先这个“联通块”并不是一定要求联通,因为我容斥的时候只要求某个边集断开,并没有要求其他的都联通呀!所以,随便找第一个点,它可以和\(n-1\)个点匹配;然后找下一个点,它可以和\(n-3\)个点匹配······最后总方案树就是它们的乘积。

现在我们有了指数级做法了(就是枚举\(E\),时间复杂度\(\Theta(n^2)\)),现在来尝试把它优化到多项式时间复杂度。

一个“联通块”的情况数,仅仅与“点数”的点数有关,这启示我们在 DP 中存下一维状态来存当前点集的大小;每条边都只有选和不选两种情况,这让我们联想到了 0/1 背包。

设 \(f_{u,i,0/1}\) 表示,\(u\)这个子树,跟\(u\)结点连着的“联通块”大小是\(i\),此时还未乘上\(i\)这个联通块的情况数的总情况数(也就是把这个子树删到只剩下\(i\)个点,不考虑\(i\)内部情况的总情况数)。显然这时\(f_{u,i,0/1}\)再乘上\(g[i]\)就是总情况数(\(g[i]=1 \times 3 \times \cdots \times (i - 3) \times (n - 1)\))。

转移的时候,考虑怎么合并把\(v\)合并到\(father_v\)上面;我们的目的是优化\(\Theta(n^2)\)枚举边集,所以看这条边钦定删掉和不钦定删掉两种情况,方程分别是:

\[f_{v,j,a} * f_{father,i,b} \rightarrow f^{'}_{father,i+j,a\oplus b}
\]
\[f_{v,j,a} * f_{father,i,b} * g[j] \rightarrow f^{'}_{father,i,a\oplus b\oplus 1}
\]

上面那个方程的含义是,不钦定删除 <v,fat> 那条边,那么它们下面的总情况数是它们的乘积;下面那个方程的意思是,不选这条边,那么下面的方案数要乘上\(v,b\)的总方案数,即\(f \times g\)。

最终的答案就等于\(\sum\limits_{i=1}^n{f_{1,i,0} - f_{1, i, 1}}\)。

总结一下,这里有几个重要的点:

1.转化为容斥的问题。

2.结合情况数只与结点数有关和边的出现与否只有两种情况,设计类似于 0/1 背包的 DP 方法。

3.树形 DP 不一定是考虑怎么从子节点们一次性推出父亲,还可以考虑怎么把子节点依次并进父亲的答案里面,这种 DP 的实现,需要把 DP 数组的其中一维拷贝一遍,具体实现看下面:

#include <bits/stdc++.h>
#define LL long long using namespace std;
const int maxn = 5e3 + 1e2;
const int mod = 1e9 + 7; int n, f[maxn][maxn][2], g[maxn], sze[maxn]; vector<int> T[maxn]; void dfs(int x, int fa)
{
int tmp[maxn][2];
memset(tmp, 0, sizeof tmp);
//cout << "HH" << endl;
//cout << x << endl;
sze[x] = 1;
f[x][1][0] = 1;
for (auto s : T[x])
{
if (s == fa) continue;
dfs(s, x);
for (int i = sze[x]; i; i--)
{
for (int j = sze[s]; j; j--)
{
for (int a = 0; a < 2; a++)
{
for (int b = 0; b < 2; b++)
{
(tmp[i + j][a ^ b] += (LL)f[x][i][a] * f[s][j][b] % mod) %= mod;
(tmp[i][a ^ b ^ 1] += (LL)f[x][i][a] * f[s][j][b] % mod * g[j] % mod) %= mod;
}
}
}
}
sze[x] += sze[s];
for (int i = 0; i <= sze[x]; i++)
{
for (int j = 0; j < 2; j++)
{
f[x][i][j] = tmp[i][j];
tmp[i][j] = 0;
}
}
}
} int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n;
for (int i = 1; i < n; i++)
{
int u, v;
cin >> u >> v;
T[u].push_back(v);
T[v].push_back(u);
}
g[0] = 1;
for (int i = 2; i <= n; i += 2)
{
g[i] = (LL)g[i - 2] * (i - 1) % mod;
}
dfs(1, 0);
int ans = 0;
for (int i = 1; i <= n; i++)
{
(ans += ((LL)f[1][i][0] - f[1][i][1] + mod) * g[i] % mod) %= mod;
}
cout << ans << endl; return 0;
}

[ARC101C] Ribbons on Tree的更多相关文章

  1. ARC101E - Ribbons on Tree

    题目链接 ARC101E - Ribbons on Tree 题解 令边集\(S \subseteq E\) 设\(f(S)\)为边集S中没有边被染色的方案数 容斥一下,那么\(ans = \sum_ ...

  2. Atcoder ARC101 Ribbons on Tree

    题解: 前面牛客网的那个比赛也有一道容斥+dp 两道感觉都挺不错的 比较容易想到的是 f[i][j]表示枚举到了i点,子树中有j个未匹配 这样的话我们需要枚举儿子中匹配状态 这样是n^2的(这是个经典 ...

  3. ARC 101E.Ribbons on Tree(容斥 DP 树形背包)

    题目链接 \(Description\) 给定一棵\(n\)个点的树.将这\(n\)个点两两配对,并对每一对点的最短路径染色.求有多少种配对方案使得所有边都至少被染色一次. \(n\leq5000\) ...

  4. [ARC101E]Ribbons on Tree(容斥,dp)

    Description 给定一棵有 \(n\) 个节点的树,满足 \(n\) 为偶数.初始时,每条边都为白色. 现在请你将这些点两两配对成 \(\frac{n}{2}\) 个无序点对.每个点对之间的的 ...

  5. ARC101E Ribbons on Tree 容斥原理+dp

    题目链接 https://atcoder.jp/contests/arc101/tasks/arc101_c 题解 直接容斥.题目要求每一条边都被覆盖,那么我们就容斥至少有几条边没有被覆盖. 那么没有 ...

  6. [atARC101E]Ribbons on Tree

    令$f(E')$表示强制$E'$中的边不被覆盖的方案数,根据容斥,$ans=\sum_{E'\subseteq E}(-1)^{|E'|}f(E')$ 对于给定的$E'$,$f(E')$即将$E'$中 ...

  7. Solution -「ARC 101E」「AT 4352」Ribbons on Tree

    \(\mathcal{Description}\)   Link.   给定一棵 \(n\) 个点的树,其中 \(2|n\),你需要把这些点两两配对,并把每对点间的路径染色.求使得所有边被染色的方案数 ...

  8. 【arc101】比赛记录

    这场还好切出了D,rt应该能涨,然而这场的题有点毒瘤,700分的D没多少人切,更别说EF了.(暴打出题人)既然这样,干脆就水一篇博客,做个简单的比赛记录. C - Candles 这题是一道一眼题,花 ...

  9. Atcoder 乱做

    最近感觉自己思维僵化,啥都不会做了-- ARC103 F Distance Sums 题意 给定第 \(i\) 个点到所有点的距离和 \(D_i\) ,要求构造一棵合法的树.满足第 \(i\) 个点到 ...

随机推荐

  1. Android系统编程入门系列之应用权限的定义与申请

    在之前关于应用内数据本地保存为文件时,曾提到应用需要申请外部存储设备的读写权限才能访问外部存储中的文件.那么针对某一种权限,应用程序具体应该怎么申请使用呢?本文将详细介绍. 应用中的权限主要分为两类, ...

  2. SpringCloud微服务实战——搭建企业级开发框架(七):自定义通用响应消息及统一异常处理

      平时开发过程中,无可避免我们需要处理各类异常,所以这里我们在公共模块中自定义统一异常,Spring Boot 提供 @RestControllerAdvice 注解统一异常处理,我们在GitEgg ...

  3. UltraSoft - Beta - 测试报告

    UltraSoft - Beta - 测试报告 在测试过程中发现了多少Bug?有哪些是Beta阶段的新Bug?有哪些是Alpha阶段没有发现的Bug? 很多Bug在开发阶段就已经经过测试了,我们在Be ...

  4. 基于JWT的Token身份验证

    ​ 身份验证,是指通过一定的手段,完成对用户身份的确认.为了及时的识别发送请求的用户身份,我们调研了常见的几种认证方式,cookie.session和token. 1.Cookie ​ cookie是 ...

  5. stm32f103系列引脚定义-功能图

    器件功能和配置(STM32F103xx增强型) STM32F103xx增强型模块框架图 STM32F103xx增强型VFQFPN36管脚图 STM32F103xx增强型LQFP100管脚图 STM32 ...

  6. Educational Codeforces Round 114 (Rated for Div. 2)题解

    还是常规的过了A,B,C还是在D上卡了... D. The Strongest Build 简化题意:给定你n组东西,每组东西都有\(c_i\)个装备,每个装备有一个武力值\(a_{i,j}\),要求 ...

  7. VS2013快捷键及技巧 / 智能插件

    复制/剪切/删除整行代码 1)如果你想复制一整行代码,只需将光标移至该行,再使用组合键"Ctrl+C"来完成复制操作,而无需选择整行. 2)如果你想剪切一整行代码,只需将光标移至该 ...

  8. JAVA笔记__窗体类/Panel类/Toolkit类

    /** * 窗体类 */ public class Main { public static void main(String[] args) { MyFrame m1 = new MyFrame() ...

  9. .net core 和 WPF 开发升讯威在线客服系统:把 .Net Framework 打包进安装程序

    本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程. 系列文章目录: https://blog.shengxunwei.com/Home/Post/44a3 ...

  10. SpringCloud config native 配置

    1.概述 最近项目使用springCloud 框架,使用config搭建git作为配置中心. 在私有化部署中,出现很多比较麻烦的和鸡肋的设计. 每次部署都需要安装gitlab 有些环境安装完gitla ...