ARC101E Ribbons on Tree 容斥原理+dp
题目链接
https://atcoder.jp/contests/arc101/tasks/arc101_c
题解
直接容斥。题目要求每一条边都被覆盖,那么我们就容斥至少有几条边没有被覆盖。
那么没有被覆盖的几条边一个可以把整棵树划分成很多连通块,每一块的贡献就是 \((siz-1)!!\)。(\(x!!=x(x-2)(x-4)\cdots\))
然后就可以 dp 了。
令 \(dp[x][i][j]\) 表示以 \(x\) 为根的子树内,\(x\) 位于一个大小为 \(i\) 的联通块,子树内有 \(j\) 条边没有被覆盖时,各种方案各个连通块的贡献之和。由于 \(x\) 所在的连通块还没有完结,所以 \(dp\) 数组不算上 \(x\) 所在连通块的贡献。(方案还是要算的)
然后就是一个基础的背包合并。
等一下,这个复杂度是?三维的 dp,要嵌套的枚举背包合并,复杂度大概是 \(O(n^4)\)。
这个肯定凉透啊。
可以发现,最后容斥的时候,我们只关心 \(j\) 的奇偶性,不关心 \(j\) 到底是几。于是我们可以把 \(j\) 那一维缩减成 \(0/1\) 的状态。
于是就是一个常规的背包合并的复杂度了,\(O(n^2)\)。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I>
inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
const int N = 5000 + 7;
const int P = 1e9 + 7;
int n, m;
int siz[N], dp[N][N][2], f[N][2], ffac[N];
struct Edge { int to, ne; } g[N << 1]; int head[N], tot;
inline void addedge(int x, int y) { g[++tot].to = y, g[tot].ne = head[x], head[x] = tot; }
inline void adde(int x, int y) { addedge(x, y), addedge(y, x); }
inline int smod(int x) { return x >= P ? x - P : x; }
inline void sadd(int &x, int y) { x += y; x >= P ? x -= P : x; }
inline void dfs(int x, int fa = 0) {
siz[x] = 1, dp[x][1][0] = 1;
for fec(i, x, y) if (y != fa) {
dfs(y, x);
for (int i = 1; i <= siz[x]; ++i)
for (int j = 1; j <= siz[y]; ++j) {
sadd(f[i + j][0], ((ll)dp[x][i][0] * dp[y][j][0] + (ll)dp[x][i][1] * dp[y][j][1]) % P);
sadd(f[i + j][1], ((ll)dp[x][i][0] * dp[y][j][1] + (ll)dp[x][i][1] * dp[y][j][0]) % P);
sadd(f[i][0], ((ll)dp[x][i][0] * dp[y][j][1] % P * ffac[j - 1] + (ll)dp[x][i][1] * dp[y][j][0] % P * ffac[j - 1]) % P);
sadd(f[i][1], ((ll)dp[x][i][0] * dp[y][j][0] % P * ffac[j - 1] + (ll)dp[x][i][1] * dp[y][j][1] % P * ffac[j - 1]) % P);
}
siz[x] += siz[y];
for (int i = 1; i <= siz[x]; ++i) dp[x][i][0] = f[i][0], dp[x][i][1] = f[i][1], f[i][0] = f[i][1] = 0;
}
}
inline void work() {
ffac[1] = 1;
for (int i = 3; i <= n; i += 2) ffac[i] = (ll)ffac[i - 2] * i % P;
dfs(1);
int ans = 0;
for (int i = 2; i <= n; i += 2) sadd(ans, (ll)(dp[1][i][0] - dp[1][i][1] + P) * ffac[i - 1] % P);
printf("%d\n", ans);
}
inline void init() {
read(n);
for (int i = 1; i < n; ++i) {
int x, y;
read(x), read(y);
adde(x, y);
}
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
ARC101E Ribbons on Tree 容斥原理+dp的更多相关文章
- ARC101E - Ribbons on Tree
题目链接 ARC101E - Ribbons on Tree 题解 令边集\(S \subseteq E\) 设\(f(S)\)为边集S中没有边被染色的方案数 容斥一下,那么\(ans = \sum_ ...
- [ARC101E]Ribbons on Tree(容斥,dp)
Description 给定一棵有 \(n\) 个节点的树,满足 \(n\) 为偶数.初始时,每条边都为白色. 现在请你将这些点两两配对成 \(\frac{n}{2}\) 个无序点对.每个点对之间的的 ...
- 熟练剖分(tree) 树形DP
熟练剖分(tree) 树形DP 题目描述 题目传送门 分析 我们设\(f[i][j]\)为以\(i\)为根节点的子树中最坏时间复杂度小于等于\(j\)的概率 设\(g[i][j]\)为当前扫到的以\( ...
- ARC 101E.Ribbons on Tree(容斥 DP 树形背包)
题目链接 \(Description\) 给定一棵\(n\)个点的树.将这\(n\)个点两两配对,并对每一对点的最短路径染色.求有多少种配对方案使得所有边都至少被染色一次. \(n\leq5000\) ...
- Codeforces 461B. Appleman and Tree[树形DP 方案数]
B. Appleman and Tree time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- [CF245H] Queries for Number of Palindromes (容斥原理dp计数)
题目链接:http://codeforces.com/problemset/problem/245/H 题目大意:给你一个字符串s,对于每次查询,输入为一个数对(i,j),输出s[i..j]之间回文串 ...
- hdu-5834 Magic boy Bi Luo with his excited tree(树形dp)
题目链接: Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others) Memory Limit: ...
- CF 461B Appleman and Tree 树形DP
Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other ...
- CF 161D Distance in Tree 树形DP
一棵树,边长都是1,问这棵树有多少点对的距离刚好为k 令tree(i)表示以i为根的子树 dp[i][j][1]:在tree(i)中,经过节点i,长度为j,其中一个端点为i的路径的个数dp[i][j] ...
随机推荐
- ### Error updating database. Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 必须声明标量变量 "@P23@P24"。(sql少一个逗号)【??】
(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,[??],?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?, ...
- 【HDOJ6667】Roundgod and Milk Tea(模拟)
题意:有n个班级,每个班级有a[i]个人,b[i]杯奶茶 每个人至多喝一杯奶茶,且不能喝自己班的 问能喝到奶茶的最多总人数 n<=1e6,a[i],b[i]<=1e9 思路: 做法一: # ...
- 牛客提高D4t3 清新题
分析 树上从下往上线性基合并即可 并不需要启发式/xyx 代码 #include<iostream> #include<cstdio> #include<cstring& ...
- spring-cloud zuul网关
API Gateway 是随着微服务(Microservice)这个概念一起兴起的一种架构模式,它用于解决微服务过于分散,没有一个统一的出入口进行流量管理的问题. 使用 Zuul 实现 API Gat ...
- leaflet-加载天地图-解决纬度偏移特别大
这几天学习 leaflet 在加载天地图时将以前的接口拿来用结果偏差了特别大(差不多是 90 度),中国纬度到了 100 多,试了改变投影和 y 轴翻转的配置都不好使,最后上网搜索到了Leaflet. ...
- mybatis缓存机制(转)
缓存在互联网系统中是非常重要的, 其主要作用是将数据保存到内存中, 当用户查询数据 时, 优先从缓存容器中获取数据,而不是频繁地从数据库中查询数据,从而提高查询性能.目 前流行的缓存服务器有Mongo ...
- php正则提取html img src地址
<?php$str='<img border="0" src="1.jpg" alt=""/><img border ...
- (转载)如何在 Github 上发现优秀的开源项目?
转载自:传送门 之前发过一系列有关 GitHub 的文章,有同学问了,GitHub 我大概了解了,Git 也差不多会使用了,但是还是搞不清 GitHub 如何帮助我的工作,怎么提升我的工作效率? 问到 ...
- hashCode -哈希值,Object中的方法,常根据实际情况重写
package cn.learn.collection; import cn.learn.basic.Phone; /* 哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值),是一个逻辑地址 ...
- 如何创建linux虚拟机
一.安装配置linux虚拟机 第1步:运行"Vmware WorkStation",看到主页面. 第2步:创建新的虚拟机,新建虚拟机向导——典型(推荐). 第3步:选择稍后安装操作 ...