@loj - 2091@ 「ZJOI2016」小星星
@description@
小 Y 是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品。她有 n 颗小星星,用 m 条彩色的细线串了起来,每条细线连着两颗小星星。
有一天她发现,她的饰品被破坏了,很多细线都被拆掉了。这个饰品只剩下了 n-1 条细线,但通过这些细线,这颗小星星还是被串在一起,也就是这些小星星通过这些细线形成了树。
小 Y 找到了这个饰品的设计图纸,她想知道现在饰品中的小星星对应着原来图纸上的哪些小星星。如果现在饰品中两颗小星星有细线相连,那么要求对应的小星星原来的图纸上也有细线相连。
小 Y 想知道有多少种可能的对应方式。只有你告诉了她正确的答案,她才会把小饰品做为礼物送给你呢。
输入格式
第一行包含两个正整数 n,m,表示原来的饰品中小星星的个数和细线的条数。
接下来 m 行,每行包含两个正整数 u,v,表示原来的饰品中小星星 u 和 v 通过细线连了起来。
这里的小星星从 1 开始标号。保证 u ≠ v,且每对小星星之间最多只有一条细线相连。 接下来 n-1 行,每行包含两个正整数 u,v,表示现在的饰品中小星星 u 和 v 通过细线连了起来。保证这些小星星通过细线可以串在一起。
输出格式
输出共一行,包含一个整数表示可能的对应方式的数量。
如果不存在可行的对应方式则输出 0。
样例输入
4 3
1 2
1 3
1 4
4 1
4 2
4 3
样例输出
6
数据范围与提示
对于所有的数据,n <= 17, m <= n*(n-1)/2。
@solution@
普通的做法人人都会:定义 dp[i][j][s] 表示以 i 为根的子树,i 对应 j,这棵子树内已经用了集合 s 的点。
然后一波枚举子集转移。然后就炸了。
我没试过 FWT 行不行,不过好像比下面的算法多个 n 的复杂度,所以估计过不了。
考虑抽象问题模型:我们要找的其实是一个满足 “树边的两个端点对应过去也存在边” 这一限制的置换。
问题在于,置换必须要满足每个元素恰好被对应一次,所以我们才要枚举子集啊之类。
但其实只有一条边相邻两个点才会产生限制。因此我们直接统计置换是很吃亏的。
我们可以把置换看成 n 个点都要被对应,通过容斥转成只有 m 个点可以被对应。
形式化来说,假如我们可被对应的点的集合为 S。
我们的原问题相当于 S 中每一个点都要被对应,通过容斥转为 T 中的点可以被对应,其中 \(T\subset S\)。
那么就回到我们一开始的树形 dp,只是少了 s 这一维,变成 dp[i][j] 表示以 i 为根的子树,i 对应 j 的方案数。
外层容斥 \(O(2^n)\),树形 dp 的复杂度为 \(O(n^3)\),所以总时间复杂度为 \(O(2^n*n^3)\)。
@accepted code@
#include<cstdio>
#include<vector>
using namespace std;
typedef long long ll;
vector<int>G[20];
void addedge(int u, int v) {
G[u].push_back(v);
G[v].push_back(u);
}
bool tag[20];
int A[20][20], n, m;
ll dp[20][20];
void dfs(int x, int f) {
for(int i=0;i<G[x].size();i++)
if( G[x][i] != f ) dfs(G[x][i], x);
for(int i=0;i<n;i++)
if( tag[i] ) {
dp[x][i] = 1;
for(int j=0;j<G[x].size();j++) {
int p = G[x][j];
if( p == f ) continue;
ll del = 0;
for(int k=0;k<n;k++)
if( A[i][k] ) del += dp[p][k];
dp[x][i] *= del;
}
}
else dp[x][i] = 0;
}
int f[1<<20];
int main() {
scanf("%d%d", &n, &m);
for(int i=1;i<=m;i++) {
int u, v; scanf("%d%d", &u, &v), u--, v--;
A[u][v] = A[v][u] = true;
}
for(int i=1;i<n;i++) {
int u, v; scanf("%d%d", &u, &v), u--, v--;
addedge(u, v);
}
int t = (1<<n); f[0] = 1;
for(int i=1;i<t;i++)
f[i] = (i&1) ? -f[i>>1] : f[i>>1];
ll ans = 0;
for(int s=0;s<t;s++) {
for(int i=0;i<n;i++)
tag[i] = !((s>>i) & 1);
dfs(0, -1);
for(int i=0;i<n;i++)
if( tag[i] ) ans = ans + f[s]*dp[0][i];
}
printf("%lld\n", ans);
}
@details@
ZJOI 的题都是神仙题 * 2。
代码倒是非常简洁。
@loj - 2091@ 「ZJOI2016」小星星的更多相关文章
- 「LOJ2091」「ZJOI2016」小星星 容斥+DP
题目描述 小 Y 是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有\(n\)颗小星星,用 \(m\)条彩色的细线串了起来,每条细线连着两颗小星星.有一天她发现,她的饰品被破坏了,很多细线都被拆掉 ...
- @loj - 2090@ 「ZJOI2016」旅行者
目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Y 来到了一个新的城市旅行.她发现了这个城市的布局是网格状的 ...
- loj2091 「ZJOI2016」小星星
ref 总的来说,就是 容斥转化为点对应到点集问题. 树形 dp 解决转化后的问题. #include <iostream> #include <cstring> #inclu ...
- 「ZJOI2016」小星星
传送门 Description Solution 容斥,考虑有多少个节点不被匹配到,求出的方案,多个点可以同时不被匹配到 状态压缩+树形dp Code #include<bits/stdc++ ...
- @loj - 2093@ 「ZJOI2016」线段树
目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Yuuka 遇到了一个题目:有一个序列 a1,a2,..., ...
- @loj - 2092@ 「ZJOI2016」大森林
目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Y 家里有一个大森林,里面有 n 棵树,编号从 1 到 n. ...
- 「ZJOI2016」解题报告
「ZJOI2016」解题报告 我大浙的省选题真是超级神仙--这套已经算是比较可做的了. 「ZJOI2016」旅行者 神仙分治题. 对于一个矩形,每次我们从最长边切开,最短边不会超过 \(\sqrt{n ...
- Loj #3042. 「ZJOI2019」麻将
Loj #3042. 「ZJOI2019」麻将 题目描述 九条可怜是一个热爱打麻将的女孩子.因此她出了一道和麻将相关的题目,希望这题不会让你对麻将的热爱消失殆尽. 今天,可怜想要打麻将,但是她的朋友们 ...
- 2090. 「ZJOI2016」旅行者 分治,最短路
2090. 「ZJOI2016」旅行者 链接 loj 思路 \((l,mid)(mid+1,r)\).考虑跨过mid的贡献. 假设选的中间那条线的点为gzy,贡献为\(dis(x,gzy)+dis(g ...
随机推荐
- Mac 安装package control
参考网址:https://packagecontrol.io/installation 复制命令就不说明了. 主要阐述下第二种,下载安装包覆盖的方法,下面不说话,依次截图.步骤可以查看参考网址 啰嗦一 ...
- SpringBoot+Shiro+mybatis整合实战
SpringBoot+Shiro+mybatis整合 1. 使用Springboot版本2.0.4 与shiro的版本 引入springboot和shiro依赖 <?xml version=&q ...
- CentOS7 下的 firewall 用法
1.firewalld的基本使用 启动: systemctl start firewalld 查看状态: systemctl status firewalld 停止: systemctl disab ...
- 全栈数据工程师养成攻略:Python 基本语法
全栈数据工程师养成攻略:Python 基本语法 Python简单易学,但又博大精深.许多人号称精通Python,却不会写Pythonic的代码,对很多常用包的使用也并不熟悉.学海无涯,我们先来了解一些 ...
- git图形化
在windows下安装git中文版客户端并连接gitlab 转载自:https://blog.whsir.com/post-1801.html 下载git Windows客户端 git客户端下载地址: ...
- Jboss 默认加载项目访问
修改JBOSS的server.xml路径为: D:\Program Files\jboss-4.2.2.GA\server\default\deploy\jboss-web.deployer\serv ...
- 从Java到C++——union的使用方法
版权声明:本文为博主原创文章,未经博主同意不得用于不论什么商业用途,转载请注明出处. https://blog.csdn.net/luoweifu/article/details/33342965 你 ...
- 关系数据库(ch.2)
2.1.1 关系 域 笛卡儿积 关系 candiate key 如果一组属性值可以唯一的标识一个元祖,但是他的子集不行,那么这是一个候选码 关系可以由三种类型 基本关系 查询关系 视图 为关系附加如下 ...
- 洛谷P2327 [SCOI2005]扫雷 [2017年5月计划 清北学堂51精英班Day1]
P2327 [SCOI2005]扫雷 题目描述 输入输出格式 输入格式: 第一行为N,第二行有N个数,依次为第二列的格子中的数.(1<= N <= 10000) 输出格式: 一个数,即第一 ...
- shared_from_this bad_weak_ptr的原因
原因:创建类A的对象的时候没有用智能指针包裹,而是直接new的裸指针. enable_from_this 的使用与实现原理说明: shared_from_this()是enable_shared_fr ...