题目链接

ARC101E - Ribbons on Tree

题解

令边集\(S \subseteq E\) 设\(f(S)\)为边集S中没有边被染色的方案数

容斥一下,那么\(ans = \sum_{S \subseteq E} (-1)^{ \| S\| f(S) }\)

那么如何求对于原边集的\(f(S)\),也就是把\(S\)集合中的边全部删掉之后的各联通块内匹配的乘积

设\(g(x)\)为大小为x的联通块内点两两匹配的方案

那么\(f(S)=\prod_{i=1}^{|S|+1}g(a_i)\)

考虑如何求ans

设\(dp[i][j]\)表示以i为跟的子树中,有j各点没有在子树种匹配(链接到父节点

转移背包一下

对于\(j=0\)的时候由于那么i节点到父亲的边是没有覆盖的,容斥系数要取反

那么

$ f[i][0]=\sum_{j=1}^{sz[i]}-1\times f[i][j]\times g(j) $

代码


#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(p,x,k) for(int p = x;p <= k;++ p)
#define per(p,x,k) for(int p = x;p >= k;-- p)
#define gc getchar()
#define pc putchar
#define LL long long
#define int long long
inline LL read() {
LL x = 0,f = 1;
char c = gc;
while(c < '0' || c > '9') c = gc;
while(c <= '9' && c >= '0') x = x * 10 + c -'0',c = gc;
return x ;
}
void print(LL x) {
if(x < 0) {
pc('-');
x = -x;
}
if(x >= 10) print(x / 10);
pc(x % 10 + '0');
}
const int maxn = 5007;
const int mod = 1e9 + 7;
int a[maxn];
int n;
struct node {
int v,next;
} edge[maxn << 1];
int num = 0,head[maxn];
inline void add_edge(int u,int v) {
edge[++ num].v = v; edge[num].next = head[u];head[u] = num;
}
int g[maxn];
int dp[maxn][maxn];
int siz[maxn];
void dfs(int x,int fa) {
static int t[maxn];
dp[x][1] = 1; siz[x] = 1;
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(v == fa) continue;
dfs(v,x);
for(int j = 0,kel = siz[v];j <= siz[x];++ j) {
for(int k = 0;k <= siz[v];++ k) {
(t[j + k] += 1ll * dp[x][j] * dp[v][k] % mod) %= mod;
}
}
siz[x] += siz[v];
for(int j = 0;j <= siz[x];++ j) dp[x][j] = t[j],t[j] = 0;
}
LL sum = 0;
for(int i = 0;i <= siz[x];i += 2) sum += mod - 1ll * dp[x][i] * g[i] % mod;
dp[x][0] = sum % mod;
}
main() {
n = read();
int u,v;
rep(i, 1,n - 1) {
u = read(),v = read();
add_edge(u,v);
add_edge(v,u);
}
g[0] = 1;
for(int i = 2;i <= n;i += 2) (g[i] = 1ll * g[i - 2] * (i - 1)) %= mod;
dfs(1,1);
print((mod - dp[1][0]) % mod);
return 0;
}
/*
4
1 2
1 3
1 4
*/

ARC101E - Ribbons on Tree的更多相关文章

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

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

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

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

  3. Atcoder ARC101 Ribbons on Tree

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

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

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

  5. [atARC101E]Ribbons on Tree

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

  6. [ARC101C] Ribbons on Tree

    神仙的容斥题与神仙的树形DP题. 首先搞一个指数级的做法:求总的.能够覆盖每一条边的方案数,通过容斥可以得到\(\text{ans}=\sum\limits_E{(-1)^{|E|}F(E)}\).其 ...

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

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

  8. Atcoder 乱做

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

  9. 【AtCoder】ARC101题解

    C - Candles 题解 点燃的一定是连续的一段,枚举左端点即可 代码 #include <bits/stdc++.h> #define enter putchar('\n') #de ...

随机推荐

  1. python网络爬虫笔记(四)

    一.python中的高阶函数算法 1.sorted()函数的排序   sorted()函数是一个高阶函数,还可以接受一个key函数来实现自定义的函数排序,key指定的函数作用于每个序列元素上,并根据k ...

  2. Python序列[1,2,3,4,5]

    序列是用于存放多个值得连续空间,并按一定顺序排列,每一个值(称为元素)都分配一个数,称为索引或位置.通过该索引可以取出相应的值. 索引 序列中的元素都是有序的.拥有自己编号(从0开始),我们可以通过索 ...

  3. 20165206 2017-2018-2 《Java程序设计》第8周学习总结

    20165206 2017-2018-2 <Java程序设计>第8周学习总结 教材学习内容总结 进程:进程是程序的一次动态执行过程,对应了从代码加载.执行至执行完毕的一个完整过程,这个过程 ...

  4. 通过安装memadmin对memcache进行可视化管理

    https://blog.csdn.net/reblue520/article/details/70792891

  5. ubuntu下的“用vim打开中文乱码,用cat打开正常显示”的解决方法

    转载 系统环境:ubuntu10.04 vim gvim完全安装 问题:终端下vim中的汉字为乱码,网上搜索了一些解决方案.但是奇怪的是,这些方法都不能实现gvim的菜单和文中汉字,终端vim下的文中 ...

  6. C# 会话,进程,线程,线程安全

    会话->进程->线程 b/s网站中,每个用户的访问为一次会话,会话中包含CPU为用户在内存中开辟空间存储的会话信息, 如Session,进程,会话拥有一个进程,同一进程下可以拥有多个线程. ...

  7. BZOJ 1706

    题解: 倍增+floyd 首先这题比较容易想到是把每个点拆点做dij 但是这样复杂度是knlogn的 这道题的k较大,所以不行 我们考虑到每走一步,其实就是在进行一次floyd 而这个可以看成矩阵乘法 ...

  8. UIActionSheet的常用方法

    enum UIActionSheetStyle : Int { case Automatic // take appearance from toolbar style otherwise uses ...

  9. mysql基本操作(一)

    1.登录mysql mysql -h localhost -u root -p  登录mysql,其中  -h是指定要连接mysql服务器的主机名    -u是指定用户   -次数登录必须用-p输入密 ...

  10. python全栈开发day101-认证组件、权限组件、频率组件

    1.Mixins类分析 这两个函数都在GenericAPIView下,这就是为什么必须搭配继承GenericAPIView的原因. 这两个主要是get_object()较为复杂. 2.认证组件源码分析 ...