神仙的容斥题与神仙的树形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. vue 解决axios请求出现前端跨域问题

    vue 解决axios请求出现前端跨域问题 最近在写纯前端的vue项目的时候,碰到了axios请求本机的资源的时候,出现了访问报404的问题.这就让我很难受.查询了资料原来是跨域的问题. 在正常开发中 ...

  2. UltraSoft - Beta - 测试报告

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

  3. 【二食堂】Beta - Scrum Meeting 3

    Scrum Meeting 3 例会时间:5.15 18:30~18:50 进度情况 组员 当前进度 今日任务 李健 1. 继续完成文本区域划词添加的功能 issue 1. 划词功能已经实现,继续开发 ...

  4. 2020BUAA软工个人博客作业-软件案例分析

    2020BUAA软工个人博客作业-软件案例分析 17373010 杜博玮 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人博客作业-软件案例分 ...

  5. 微信小程序实现上拉和下拉加载更多

    在上一篇文章中,我们知道了使用 scroll-view 可以实现上拉加载更多,但是由于 scroll-view 的限制,它无法实现下拉加载更多,这篇文章我们使用 view 组件来实现 上拉和下拉加载更 ...

  6. 树链剖分好(du)题(liu)选做

    1.luogu P4315 月下"毛景树" 题目链接 前言: 这大概是本蒟蒻A掉的题里面码量最大的一道题了.我自认为码风比较紧凑,但还是写了175行. 从下午2点多调到晚上8点.中 ...

  7. Spring MVC:HandlerMapping

    HandlerMapping 的类图 Spring中存在两种类型的handlers.第一种是 handler mappings(处理程序映射).它们的角色定位与前面所描述的功能完全相同.它们尝试将当前 ...

  8. Python gpu 显卡小工具 gpu

    安装 pip install gpustat 或者 换源 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade gpust ...

  9. oracle 归档日志:db_recovery_file_dest、log_archive_dest和log_archive_dest_n的区别和使用

    概念: db_recovery_file_dest:默认的指定闪回恢复区路径 log_archive_dest:指定归档文件存放的路径,所有归档路径必须是本地的,默认为''.log_archive_d ...

  10. Go websocket EOF bug

    背景 使用的 golang.org/x/net/websocket 包,前端一发来消息就报错 if err = websocket.Message.Receive(ws, &msg); err ...