【bzoj 4455】小星星(树型DP+容斥原理+dfs建树和计算的2种方式)
题意:给一个n个点的图和一个n个点的树,求图和树上的点一一对应的方案数。(N<=17)
解法:
1.在树的结构上进行tree DP,f[i][j]表示树上点 i 对应图上点 j 时,这个点所在子树的方案数。O(n^3)。
2.我们可以发现如果按这个定义进行DP,“一 一对应”的关系挺难保证。若枚举出全排列得到对应关系,这样就C(n,n)=n! 只能拿到暴力分;那么我们就不限制“一 一对应”而改为“一对多”的关系进行tree DP,利用容斥原理达到O(2^n)的复杂度。(P.S.至于为什么用容斥原理我也不清楚,待我弄懂之后我会再更新的。 2个月后的今天 我说:“应该不会有更新了......”≡[。。]≡)
3.这题的容斥原理应用是这样的:用二进制数枚举出每次DP有哪些数没有对应的树上的点,将所有情况下的DP方案数之和按求补集的公式来求就是“所有数都一一对应树上的点”的答案。
下图中圆圈1表示数1没有对应的点的方案数,依次类推。有颜色部分是我们要求的补集。
下面附上代码——
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 7 typedef long long LL; 8 const int N=20,M=400; 9 struct node{int x,y,next;}a[2*N]; 10 int last[N],len; 11 bool v[N][N],vis[N]; 12 LL f[N][N]; 13 int b[N],bt; 14 15 void add(int x,int y) 16 { 17 len++; 18 a[len].x=x,a[len].y=y; 19 a[len].next=last[x],last[x]=len; 20 } 21 22 void dfs(int x,int fa) 23 { 24 /*for(int k=last[x];k;k=a[k].next) 25 { 26 int y=a[k].y; 27 if(y==fa)continue; 28 dfs(y,x); 29 } 30 for (int kk=1;kk<=bt;kk++) 31 { 32 int i=b[kk]; 33 f[x][i]=1; 34 for (int k=last[x];k;k=a[k].next) 35 { 36 int y=a[k].y; 37 if (y==fa) continue; 38 LL h=0; 39 for (int kkk=1;kkk<=bt;kkk++) 40 { 41 int j=b[kkk]; 42 if (v[i][j]) h+=f[y][j]; 43 } 44 f[x][i]*=h; 45 } 46 }*///边建树,边不重复地DP 47 if (vis[x]) return; 48 for (int kk=1;kk<=bt;kk++) 49 { 50 int i=b[kk]; 51 f[x][i]=1; 52 for (int k=last[x];k;k=a[k].next) 53 { 54 int y=a[k].y; 55 if (y==fa) continue; 56 dfs(y,x); 57 vis[y]=true; 58 LL h=0; 59 for (int kkk=1;kkk<=bt;kkk++) 60 { 61 int j=b[kkk]; 62 if (v[i][j]) h+=f[y][j]; 63 } 64 f[x][i]*=h; 65 } 66 }//打标记,快一点 67 } 68 69 int main() 70 { 71 int n,m; 72 scanf("%d%d",&n,&m); 73 memset(v,false,sizeof(v)); 74 for (int i=1;i<=m;i++) 75 { 76 int x,y; 77 scanf("%d%d",&x,&y); 78 v[x][y]=v[y][x]=true; 79 } 80 memset(last,0,sizeof(last)); 81 len=0; 82 for (int i=1;i<n;i++) 83 { 84 int x,y; 85 scanf("%d%d",&x,&y); 86 add(x,y),add(y,x); 87 } 88 LL ans=0; 89 for (int i=1;i<(1<<n);i++) 90 { 91 bt=0; 92 for (int j=1;j<=n;j++) 93 if (i&(1<<(j-1))) b[++bt]=j; 94 memset(vis,false,sizeof(vis)); 95 dfs(1,0); 96 LL h=0; 97 for (int j=1;j<=bt;j++) 98 h+=f[1][b[j]]; 99 if ((n-bt)%2==0) ans+=h;//按补集 100 else ans-=h; 101 } 102 printf("%lld\n",ans); 103 return 0; 104 }
转载于:https://www.cnblogs.com/konjak/p/5876427.html
【bzoj 4455】小星星(树型DP+容斥原理+dfs建树和计算的2种方式)相关推荐
- 其他OJ 树型DP 选课
在朱全民的PPT介绍的一个树型DP经典题,<选课>,中文题目,不结束 找了很久找到了可以提交的OJ,重庆八中 http://www.cqoi.net:2012/JudgeOnline/pr ...
- 【树型DP】加分二叉树
问题 b: [树型DP]加分二叉树 时间限制: 1 Sec 内存限制: 64 MB 提交: 8 解决: 6 [提交] [状态] [讨论版] [命题人:admin] 题目描述 科技忽略了过程就是魔法 ...
- 二叉苹果树(树型DP+背包)
二叉苹果树 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点).这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号 ...
- POJ3342 Party at Hali-Bula(树型DP求最大独立集+唯一解判断)
题意: 公司参加聚会,要求员工不能和他的上司同时参加,求最多能参加几个人并且判断解是否唯一. 要点: 树型DP的经典题,用dp[u][1]表示选取u的最大值,dp[u][0]表示不选取u的最大值,容易 ...
- 虚树+树型DP SDOI2011消耗战
<虚树+树型DP> SDOI2011消耗战 #include <iostream> #include <cstdio> #include <cstring&g ...
- 洛谷P3354 Riv河流 [IOI2005] 树型dp
正解:树型dp 解题报告: 传送门! 简要题意:有棵树,每个节点有个权值w,要求选k个节点,最大化∑dis*w,其中如果某个节点到根的路径上选了别的节点,dis指的是到达那个节点的距离 首先这个一看就 ...
- hihocoder 1479 三等分 树型dp
描述 小Hi最近参加了一场比赛,这场比赛中小Hi被要求将一棵树拆成3份,使得每一份中所有节点的权值和相等. 比赛结束后,小Hi发现虽然大家得到的树几乎一模一样,但是每个人的方法都有所不同.于是小Hi希 ...
- 蓝桥杯:生命之树【树型dp】
之前本菜还没学树型dp的时候,下意识地认为这个东西很难,感觉这个东西结合了搜索+dp这两座算法界的大山必定很难,但万万没想到啊,这个东西很像我之前讲的记忆化搜索,甚至我认为,记忆化搜索的一个作用就是将 ...
- 【树型DP】BZOJ1564 二叉查找树(noi2009)
标签: 二叉查找树 [题目描述] 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左儿子结点的数据值大,而比它右儿子结点的数据值小. 另一方面,这棵查找树中每个结点都有一个权值 ...
最新文章
- [Vue CLI 3] 插件开发之 registerCommand 到底做了什么
- Swift3.0语言教程获得一个公共的前缀
- 【转】 Pro Android学习笔记(二九):用户界面和控制(17):include和merge
- 「拨云见日」英特尔揭秘短视频背后的二三事
- php里h和h的区别吗,编码h264h和h264b有什么区别
- WebBrowser中html元素如何触发winform事件
- Bash 入门教程10-处理用户输入
- 什么情况下不应该使用深度学习?
- HTML5-Video(视屏播放)
- 异步任务+JSON解析+ListView分页
- 阿里、腾讯、知乎裁员 那些被裁的程序员怎么办?
- 最后采用加权求和的方式得到样本的_一种婴幼儿视力自动检测方法与流程
- java毕业设计软件源代码SSM酒店管理系统|旅店管理
- OA、CRM、ERP、BPM系统
- mysql主从配置干什么_mysql主从配置之slave_exec_mode=IDEMPOTENT详解
- 鲲鹏、昇腾、欧拉——计算产业的矩阵已足够宽广
- 速达财务软件未能连接服务器,速达3000财务软件使用常见问题
- AJAX-客户端服务器端通信
- 基尔霍夫(kirchhoff)矩阵树定理
- Virtual Box安装Ubuntu