题目描述

小 Y 是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品。她有\(n\)颗小星星,用 \(m\)条彩色的细线串了起来,每条细线连着两颗小星星。有一天她发现,她的饰品被破坏了,很多细线都被拆掉了。这个饰品只剩下了\(n-1\)条细线,但通过这些细线,这颗小星星还是被串在一起,也就是这些小星星通过这些细线形成了树。小 Y 找到了这个饰品的设计图纸,她想知道现在饰品中的小星星对应着原来图纸上的哪些小星星。如果现在饰品中两颗小星星有细线相连,那么要求对应的小星星原来的图纸上也有细线相连。小 Y 想知道有多少种可能的对应方式。只有你告诉了她正确的答案,她才会把小饰品做为礼物送给你呢。

输入

第一行包含两个正整数\(n,m\),表示原来的饰品中小星星的个数和细线的条数。

接下来\(n-1\)行,每行包含两个正整数\(u,v\),表示原来的饰品中小星星\(u\)和 \(v\)通过细线连了起来。

这里的小星星从 开始标号。保证 ,且每对a小星星之间最多只有一条细线相连。 接下来 行,每行包含两个正整数 ,表示现在的饰品中小星星 和 通过细线连了起来。保证这些小星星通过细线可以串在一起。

输出

输出共一行,包含一个整数表示可能的对应方式的数量。

如果不存在可行的对应方式则输出\(0\)。

样例

样例输入

4 3
1 2
1 3
1 4
4 1
4 2
4 3

样例输出

6

数据范围

对于所有的数据\(n\leq 17\),\(m\leq \frac{n(n-1)}{2}\)。

题解

首先,我诈尸了。

第二,这是道容斥原理好题目……

考虑这个问题的等价形式,对树上的点进行重标号,让重标号的点可以嵌入原图(即,树上相邻的点在原图也相邻),并且满足每个点不会有相同的编号,然后问重标号的方案数。

于是一个简单的状压\(DP\)就呼之欲出了:\(f[i][s]\)表示以\(i\)为根的子树,把\(s\)里的数全都标号了,方案数是多少?这个可以很容易地使用子集转移做到\(O(n^k3^n)\),\(k\)随你实现的方法有所变化,然而不管\(k\)取多少都没办法过……毕竟有一个\(3^n\)在那里。

我们似乎没有办法了,不如考虑没有“两个点的标号不能相同”这个限制,这就非常好做了,\(f[i][j]\)表示以\(i\)为根的子树的答案,并且\(i\)的标号是\(j\)的方案。状态转移方程式显然很好写:

\[f[i][j]=\prod_{s\in son_i}\left(\sum_{A_{k,j}=1}f[s][k]\right)
\]

然后这个东西显然会求出重复标号,我们稍微想想就知道可以容斥出来答案。\(2^n\)枚举一下哪些点不能被使用,奇数个就减掉,偶数个就加上,感性理解一下看起来是对的。很显然,强制要求一些点不选并不会增加\(DP\)难度,复杂度大约是\(O(n^32^n)\),我是不知道怎么继续优化了……用一些优化方式可以剪掉一些不必要的情况,卡卡常就过了。

\(Code:\)

#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 20
#define ll long long
int n, m, A[N][N];
int tar[N << 1], nex[N << 1], fir[N], cnt;
ll f[N][N];
vector<int> ver[N];
void Add(int a, int b)
{
++cnt;
tar[cnt] = b;
nex[cnt] = fir[a];
fir[a] = cnt;
}
void Dfs(int r, int fa, int s)
{
for (int i = fir[r]; i; i = nex[i])
{
int v = tar[i];
if (v != fa)
Dfs(v, r, s);
}
for (int i = 1; i <= n; i++)
{
if (s & (1 << (i - 1)))
continue;
f[r][i] = 1;
for (int j = fir[r]; j; j = nex[j])
{
int v = tar[j];
if (v != fa) {
ll sum = 0;
int t = ver[i].size();
for (int k = 0; k < t; k++)
{
int p = ver[i][k];
if (s & (1 << (p - 1)))
continue;
sum += f[v][p];
}
f[r][i] *= sum;
}
}
}
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++)
{
int a, b;
scanf("%d%d", &a, &b);
ver[a].push_back(b);
ver[b].push_back(a);
}
for (int i = 1; i < n; i++)
{
int u, v;
scanf("%d%d", &u, &v);
Add(u, v), Add(v, u);
}
ll ans = 0;
for (int i = 0; i < (1 << n); i++)
{
Dfs(1, 0, i);
ll sum = 0;
int bit = 1;
for (int j = 1; j <= n; j++)
if (i & (1 << (j - 1)))
bit = -bit;
else
sum += f[1][j];
ans += bit * sum;
}
printf("%lld\n", ans);
}

「LOJ2091」「ZJOI2016」小星星 容斥+DP的更多相关文章

  1. [BZOJ4455][ZJOI2016]数星星(容斥DP)

    4455: [Zjoi2016]小星星 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 707  Solved: 419[Submit][Status] ...

  2. 4455[Zjoi2016]小星星 容斥+dp

    4455: [Zjoi2016]小星星 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 527  Solved: 317[Submit][Status] ...

  3. HDU 5794 A Simple Chess (容斥+DP+Lucas)

    A Simple Chess 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5794 Description There is a n×m board ...

  4. [CF1086E]Beautiful Matrix(容斥+DP+树状数组)

    给一个n*n的矩阵,保证:(1)每行都是一个排列 (2)每行每个位置和上一行对应位置不同.求这个矩阵在所有合法矩阵中字典序排第几.考虑类似数位DP的做法,枚举第几行开始不卡限制,那么显然之前的行都和题 ...

  5. 【BZOJ3622】已经没有什么好害怕的了 容斥+DP

    [BZOJ3622]已经没有什么好害怕的了 Description Input Output Sample Input 4 2 5 35 15 45 40 20 10 30 Sample Output ...

  6. $bzoj2560$ 串珠子 容斥+$dp$

    正解:容斥+$dp$ 解题报告: 传送门$QwQ$ $umm$虽然题目蛮简练的了但还是有点难理解,,,我再抽象一点儿,就说有$n$个点,点$i$和点$j$之间有$a_{i,j}$条无向边可以连,问有多 ...

  7. loj#2542. 「PKUWC2018」随机游走(MinMax容斥 期望dp)

    题意 题目链接 Sol 考虑直接对询问的集合做MinMax容斥 设\(f[i][sta]\)表示从\(i\)到集合\(sta\)中任意一点的最小期望步数 按照树上高斯消元的套路,我们可以把转移写成\( ...

  8. LOJ#503. 「LibreOJ β Round」ZQC 的课堂(容斥+FHQTreap)

    题面 传送门 题解 首先\(x\)和\(y\)两维互相独立,可以分开考虑,我们以\(x\)为例 我们把\(x\)做个前缀和,那么就是问有多少\(i\)满足\(s_is_{i-1}<0\),其中\ ...

  9. loj2542 「PKUWC2018」随机游走 MinMax 容斥+树上高斯消元+状压 DP

    题目传送门 https://loj.ac/problem/2542 题解 肯定一眼 MinMax 容斥吧. 然后问题就转化为,给定一个集合 \(S\),问期望情况下多少步可以走到 \(S\) 中的点. ...

随机推荐

  1. webpack在nodejs中应用(支持es6语法及热加载)

    安装 npm i webpack webpack-cli @babel/core babel-loader @babel/preset-env @babel/node clean-webpack-pl ...

  2. [Flutter] Flexible the Widget height to available space

    Let's say you set widget height to 200, but to different screen, there might not be enough space for ...

  3. How to change hostname on debian

    How to change hostname on Debian 10 Linux last updated July 13, 2019 in CategoriesDebian / Ubuntu, L ...

  4. WinDbg常用命令系列---显示数字格式化.formats

    .formats (Show Number Formats) .formats命令在当前线程和进程的上下文中计算表达式或符号,并以多种数字格式显示它. .formats expression 参数: ...

  5. WinDbg的环境变量

    有很多的环境变量,主要分为常规环境变量和内核模式环境变量.下面分别列出. 常规环境变量 下表列出了可在用户模式和内核模式调试的环境变量. 变量 含义 _NT_DEBUGGER_EXTENSION_PA ...

  6. 7kyu kata

    https://www.codewars.com/kata/isograms/train/java CW 大神 solution: public class isogram { public stat ...

  7. 洛谷 P4071 [SDOI2016]排列计数 题解

    P4071 [SDOI2016]排列计数 题目描述 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳 ...

  8. 洛谷 P1536 村村通

    目录 题目 思路 \(Code\) 题目 P1536 村村通 思路 并查集,一开始连通快的数量为\(n\),输入\(m\)条边时如果该边起点和终点不在同一联通块内就合并并让联通块数量减一,最后输出联通 ...

  9. 使用javascript获取父级元素

    之前jquery用多了习惯了它那简洁的写法,后来使用ES6进行编写的时候,需要使用类似$(this).parent();来获取点击元素所属的父级元素时发现,es6中的class下的this指向是cla ...

  10. ubuntu之路——day11.7 end-to-end deep learning

    在传统的数据处理系统或学习系统中,有一些工作需要多个步骤进行,但是端到端的学习就是用一个神经网络来代替中间所有的过程. 举个例子,在语音识别中: X(Audio)----------MFCC----- ...