前言

我容斥方面很菜啊,总是一头雾水,于是决心好好学容斥 (从水题刷起)

题意简介

题面链接

题目大意

给出一个nnn个点,mmm条边的无向无重边、无自环的图,再给出一棵nnn个点的树
定义一种对应为:让每个树中的点uuu都对应一个图中的点u′u'u′(图中所有点都要被对应,也即对应的点必须不同)
问有多少对应方式使得对于树中每一组有边相连的点对u,vu,vu,v,图中的对应点u′,v′u',v'u′,v′之间也有边相连

数据范围

n≤17,m≤n∗(n−1)/2n\le17,m\le n*(n-1)/2n≤17,m≤n∗(n−1)/2

题解

部分分

直接dp
f[i][j][S]f[i][j][S]f[i][j][S]
表示iii节点及其子树都已经做完,iii对应的图中节点是jjj,iii节点及其子树中的点对应图中的节点集合是SSS,此时的方案数
具体流程就是枚举每个状态
转移的时候是枚举子节点以及子节点对应的点,然后还要枚举子集(Θ(3n)\Theta(3^n)Θ(3n))
总复杂度是Θ(3nn2)\Theta(3^nn^2)Θ(3nn2)

正解

考虑部分分的复杂度瓶颈在于枚举子集,考虑容斥优化
我们发现,由于有个限制“对应的点必须不同”,所以并不好做
考虑我们现放宽条件,求出能任意对应的时候的答案,再把哪些对应的点有相同的方案删去
打出容斥的式子:
∣A1∪A2∪...∪An∣=∑i=1n(−1)i−1∑∣T∣=i,T={x1...xi}∣Ax1∩Ax2∩...∩Axi∣|{A_1}\cup{A_2}\cup...\cup{A_n}|=\sum_{i=1}^n(-1)^{i-1}\sum_{|T|=i,T=\{x_1...x_i\}}|{A_{x_1}}\cap{A_{x_2}}\cap...\cap{A_{x_i}}|∣A1​∪A2​∪...∪An​∣=i=1∑n​(−1)i−1∣T∣=i,T={x1​...xi​}∑​∣Ax1​​∩Ax2​​∩...∩Axi​​∣
非常经典
设AiA_iAi​表示未匹配iii的方案,设UUU为所有的方案
那么相当于我们要求的就是∣U∣−∣A1∪A2∪...∪An∣|U|-|{A_1}\cup{A_2}\cup...\cup{A_n}|∣U∣−∣A1​∪A2​∪...∪An​∣
代入一下就是Ans=∣U∣−∑i=1n(−1)i−1∑∣T∣=i,T={x1...xi}∣Ax1∩Ax2∩...∩Axi∣=∣U∣+∑i=1n(−1)i∑∣T∣=i,T={x1...xi}∣Ax1∩Ax2∩...∩Axi∣\begin{aligned} Ans&=|U|-\sum_{i=1}^n(-1)^{i-1}\sum_{|T|=i,T=\{x_1...x_i\}}|{A_{x_1}}\cap{A_{x_2}}\cap...\cap{A_{x_i}}|\\ &=|U|+\sum_{i=1}^n(-1)^i\sum_{|T|=i,T=\{x_1...x_i\}}|{A_{x_1}}\cap{A_{x_2}}\cap...\cap{A_{x_i}}| \end{aligned}Ans​=∣U∣−i=1∑n​(−1)i−1∣T∣=i,T={x1​...xi​}∑​∣Ax1​​∩Ax2​​∩...∩Axi​​∣=∣U∣+i=1∑n​(−1)i∣T∣=i,T={x1​...xi​}∑​∣Ax1​​∩Ax2​​∩...∩Axi​​∣​
∣Ax1∩Ax2∩...∩Axi∣|{A_{x_1}}\cap{A_{x_2}}\cap...\cap{A_{x_i}}|∣Ax1​​∩Ax2​​∩...∩Axi​​∣的意义是匹配的点不包含x1⋅⋅⋅xix_1···x_ix1​⋅⋅⋅xi​,做的时候可以枚举TTT的补集。∣U∣|U|∣U∣的答案是空集补集的贡献。全集补集为空集、贡献为000,所以不用枚举
做的时候枚举所有的点对应的点的集合SSS,代表对应的点不能在SSS之外,然后就Θ(n3)\Theta(n^3)Θ(n3)的树形dp即可,总复杂度Θ(2n∗n3)\Theta(2^n*n^3)Θ(2n∗n3)
复杂度分析数值比较大,但是容易发现后面的Θ(n3)\Theta(n^3)Θ(n3)是不满的,复杂度分析在1e81e81e8多一点,几乎不用卡常即可过

代码

贴上ac代码

#include<cstdio>
#include<cctype>
#include<algorithm>
#include<vector>
namespace fast_IO
{const int IN_LEN=10000000,OUT_LEN=10000000;char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf,*lastin=ibuf+IN_LEN,*lastout=obuf+OUT_LEN-1;inline char getchar_(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,IN_LEN,stdin),ih==lastin)?EOF:*ih++;}inline void putchar_(const char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}inline void flush(){fwrite(obuf,1,oh-obuf,stdout);}
}
using namespace fast_IO;
#define getchar() getchar_()
#define putchar(x) putchar_((x))
#define rg register
typedef long long LL;
template <typename T> inline T max(const T a,const T b){return a>b?a:b;}
template <typename T> inline T min(const T a,const T b){return a<b?a:b;}
template <typename T> inline void mind(T&a,const T b){a=a<b?a:b;}
template <typename T> inline void maxd(T&a,const T b){a=a>b?a:b;}
template <typename T> inline T abs(const T a){return a>0?a:-a;}
template <typename T> inline void swap(T&a,T&b){T c=a;a=b;b=c;}
template <typename T> inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);}
template <typename T> inline T lcm(const T a,const T b){return a/gcd(a,b)*b;}
template <typename T> inline T square(const T x){return x*x;};
template <typename T> inline void read(T&x)
{char cu=getchar();x=0;bool fla=0;while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}while(isdigit(cu))x=x*10+cu-'0',cu=getchar();if(fla)x=-x;
}
template <typename T> inline void printe(const T x)
{if(x>=10)printe(x/10);putchar(x%10+'0');
}
template <typename T> inline void print(const T x)
{if(x<0)putchar('-'),printe(-x);else printe(x);
}
const int maxn=19;
int n,m,bit[maxn];
bool edge[maxn][maxn];
std::vector<int>E[maxn];
int stack[maxn],top;
inline void get(int x)
{top=0;for(rg int i=1;x;i++,x>>=1)if(x&1)stack[++top]=i;
}
LL f[maxn][maxn],ans;
void dfs(const int u,const int fa)
{for(rg int t=1;t<=top;t++)f[u][t]=1;for(std::vector<int>::iterator Pos=E[u].begin();Pos!=E[u].end();Pos++){const int v=*Pos;if(v==fa)continue;dfs(v,u);for(rg int t=1;t<=top;t++){LL val=0;for(rg int l=1;l<=top;l++)if(edge[stack[t]][stack[l]])val+=f[v][l];f[u][t]*=val;}}
}
int main()
{bit[1]=1;for(rg int i=2;i<=18;i++)bit[i]=bit[i-1]<<1; read(n),read(m);for(rg int i=1;i<=m;i++){int u,v;read(u),read(v);edge[u][v]=edge[v][u]=1;}for(rg int i=1;i<n;i++){int u,v;read(u),read(v);E[u].push_back(v),E[v].push_back(u);}for(rg int i=1;i<bit[n+1];i++){get(i);dfs(1,0);LL val=0;for(rg int j=1;j<=top;j++)val+=f[1][j];if((top&1)==(n&1))ans+=val;else ans-=val;}print(ans);return flush(),0;
}

总结

这是容斥的经典模式,写篇博客来记录&纪念一下

朴素容斥原理[ZJOI2016][bzoj4455]小星星相关推荐

  1. uoj #185. 【ZJOI2016】小星星

    #185. [ZJOI2016]小星星 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有 nn 颗小星星,用 mm 条彩色的细线串了起来,每条细线连着两颗小星星.有一天她发现,她的饰品被破坏 ...

  2. 【BZOJ4455】【UOJ185】【ZJOI2016】小星星(树形DP,容斥原理)

    Description http://uoj.ac/problem/185 Solution 单考虑下面Code中的那个dp函数,设fi,jfi,jf_{i,j}表示iii映射到j" rol ...

  3. CQNKP4070【ZJOI2016】小星星

    问题描述 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有n颗小星星,用m条彩色的细线串了起来,每条细线连着两颗小星星.有一天她发现,她的饰品被破坏了,很多细线都被拆掉了.这个饰品只剩下了n ...

  4. BZOJ4455 小星星

    闲扯 看到多个限制条件的计数题目,就想到容斥原理 思路 题目要求两个条件 - 编号一一对应 - 树上存在的边,在图上映射到的点上也应该存在 考虑一个暴力的dp,设\(dp_{i,j}\)表示i点编号对 ...

  5. UOJ #185【ZJOI2016】 小星星

    题目链接:小星星 首先有个暴力很好想.令\(f_{i,j,S}\)表示把\(i\)这棵子树对应到原图中的\(S\)集合,\(i\)号点对应到了\(j\)号点的方案数.这玩意儿复杂度是\(O(3^nn^ ...

  6. [容斥 状压DP 树形DP] BZOJ 4455 [Zjoi2016]小星星 UOJ #185 【ZJOI2016】小星星

    杜老师说的哦 据说有人n*3^n卡过去 ? UOJ上需要卡常哦 #include<cstdio> #include<cstdlib> #include<algorithm ...

  7. 对于容斥原理反演的思考和总结

    前言 我还是太菜了 容斥之类的方法并不能熟练应用 于是这次我就认真学习了一下容斥 你可能会发现,容斥与反演很多时候都会同时出现 那么,这两个东西分别是什么.究竟有什么关系呢? 容斥 我们先从定义说起 ...

  8. kinectfusion解析_2019/02/09 对于KinectFusion 的理解

    网上有很多关于Kinect Fusion 的详细介绍,包括各个部分的算法,思路,以及应用上的限制和优化. 在此就不多介绍了. KinectFusion 提供了非常基础的用RGB-D 相机实现的 Den ...

  9. 使用MAKER进行注释: 如何避免多轮MAKER时的重复运算

    通常而言,我们会运行不只一轮的MAKER.如果参考组序列没有变化,那么有一些计算只需要做一次就行了,例如将EST, Repeat和Protein序列比对到参考基因组,得到它们对应的位置. 我们有三种方 ...

最新文章

  1. 写给大忙人看的死锁详解
  2. python stdout stderr 一起输出_python – 使用subprocess.Popen()时,stderr和stdout没有输出
  3. c语言mfc弹出窗口函数,CMFCDesktopAlertWnd实现桌面弹出消息框
  4. .net core实践系列之短信服务-架构设计
  5. [原创]java获取word里面的文本
  6. 值大于为此列指定的允许精度_电能质量测试精度会受到哪些因素影响?如何解决?...
  7. c++求数组中出现频率最高的数
  8. 如何成为一名汽车软件工程师?
  9. Zemax操作20--柱透镜
  10. java ehcache使用_ehcache使用报错
  11. python使用Future、async、await、wait、gather、ensure_future、as_completed
  12. 汉诺塔问题的Java实现(递归与非递归)
  13. [未来成长] 分享:《麦肯锡教我的写作武器》如何写出一篇具有逻辑表现力的文案...
  14. 名帖37 桂馥 隶书《立轴三幅》
  15. (js)switch
  16. 卸载Photoshop
  17. Linux x8664汇编,xorl%eax,g86生成的x86_64汇编代码中的%eax
  18. 地图数据赋能ADAS的探索与实践(转载)
  19. c# 备份oracle waitforexit()方法死锁,从过程的空的stdout原因同步读数据死锁[重复](Synchronized reading dat...
  20. adam算法效果差原因_深度学习优化器-Adam两宗罪

热门文章

  1. 微服务和SOA架构的区别
  2. SpringMVC的请求-获得请求参数-请求参数类型
  3. SpringMVC的数据响应-回写数据-直接回写字符串(应用)
  4. 企业微服务:实现crud操作之dao接口
  5. 从一个极简的微服务架构开始
  6. Bootstrap全局css样式_按钮
  7. goland设置goroot_go环境搭建-goland使用、gopath、go命令
  8. 代理、委托、钩子与打桩
  9. 【报错笔记】在做struts项目时,所有项目代码没问题但就是报404错误。
  10. Redis源码编译安装