【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 }
【bzoj 4455】小星星(树型DP+容斥原理+dfs建树和计算的2种方式)的更多相关文章
- BZOJ 1369 Gem - 树型dp
传送门 题目大意: 给一棵树上每个点一个正权值,要求父子的权值不同,问该树的最小权值和是多少. 题目分析: 证不出来最少染色数,那就直接信仰用20来dp吧:dp[u][i]表示u节点权值赋为i时u子树 ...
- 选课 - 树型DP(孩子兄弟建树法)
题目描述 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了 N(N<300)门的选修课程,每个学生可选课程的数量 M 是给定的.学生选修了这M门课并考核通 ...
- BZOJ 1564 :[NOI2009]二叉查找树(树型DP)
二叉查找树 [题目描述] 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左儿子结点的数据值大,而比它右儿子结点的数据值小. 另一方面,这棵查找树中每个结点都有一个权值,每个结 ...
- BZOJ 2286 消耗战 - 虚树 + 树型dp
传送门 题目大意: 每次给出k个特殊点,回答将这些特殊点与根节点断开至少需要多少代价. 题目分析: 虚树入门 + 树型dp: 刚刚学习完虚树(好文),就来这道入门题签个到. 虚树就是将树中的一些关键点 ...
- BZOJ 1509 逃学的小孩 - 树型dp
传送门 题目大意: 在一棵树中, 每条边都有一个长度值, 现要求在树中选择 3 个点 X.Y. Z , 满足 X 到 Y 的距离不大于 X 到 Z 的距离, 且 X 到 Y 的距离与 Y 到 Z 的距 ...
- BZOJ 1864 三色二叉树 - 树型dp
传送门 题目大意: 给一颗二叉树染色红绿蓝,父亲和儿子颜色必须不同,两个儿子颜色必须不同,问最多和最少能染多少个绿色的. 题目分析: 裸的树型dp:\(dp[u][col][type]\)表示u节点染 ...
- POJ 3342 - Party at Hali-Bula 树型DP+最优解唯一性判断
好久没写树型dp了...以前都是先找到叶子节点.用队列维护来做的...这次学着vector动态数组+DFS回朔的方法..感觉思路更加的清晰... 关于题目的第一问...能邀请到的最多人数..so ea ...
- 洛谷P3354 Riv河流 [IOI2005] 树型dp
正解:树型dp 解题报告: 传送门! 简要题意:有棵树,每个节点有个权值w,要求选k个节点,最大化∑dis*w,其中如果某个节点到根的路径上选了别的节点,dis指的是到达那个节点的距离 首先这个一看就 ...
- 【POJ 3140】 Contestants Division(树型dp)
id=3140">[POJ 3140] Contestants Division(树型dp) Time Limit: 2000MS Memory Limit: 65536K Tot ...
随机推荐
- 一个上传图片,预览图片的小demo
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 基于SVM的字母验证码识别
基于SVM的字母验证码识别 摘要 本文研究的问题是包含数字和字母的字符验证码的识别.我们采用的是传统的字符分割识别方法,首先将图像中的字符分割出来,然后再对单字符进行识别.首先通过图像的初步去噪.滤波 ...
- 安装蓝鲸paas社区版
安装蓝鲸paas社区版http://docs.bk.tencent.com/bkce_install_guide/setup/get_ready.html#hostssystemctl stop fi ...
- Docker Java 镜像基础(四)
基于官方提供的centos 7.2.1511 基础镜像构建JDK 和tomcat 镜像,先构建JDK镜像,然后在基于JDK镜像构建tomcat镜像 构建 centos:latest 基础镜像: # 下 ...
- 【Docker】CentOS7 上无网络情况下安装
自建虚拟机,但是连接不上网络,只能通过下载rpm包进行安装docker 环境:CentOS 7.3.1611 x64 rpm镜像下载地址用的阿里的https://mirrors.aliyun.com/ ...
- 【Oracle】下载11.2.0.4的地址
https://updates.oracle.com/download/13390677.html 这个地址就是下载Oracle 11.2.0.4版本的地址,需要有metalink账号才可以下载
- 【Oracle】密码文件相关
Oracle数据库的orapwd命令,主要用来建立密码(口令)文件. 一.查看帮助信息 [oracle@oracle11g dbs]$ orapwd Usage: orapwd file=<fn ...
- cobalt strike出现连接超时情况解决办法
服务器安装好teamserver服务后,进行连接,此时出现了连接超时的情况 检查方法: 一.检查端口是否正常开启 netstat -an | grep <设置的端口号>centos7可以用 ...
- Linux sudo权限提升漏洞整改方法
一.漏洞概述 1月26日,Sudo发布安全通告,修复了一个类Unix操作系统在命令参数中转义反斜杠时存在基于堆的缓冲区溢出漏洞.当sudo通过-s或-i命令行选项在shell模式下运行命令时,它将在命 ...
- join 查询优化
在开发中往往会出现查询多表联查的情况,那么就会用到 join 查询. Join查询种类 为了方便说明,先定义一个统一的表,下面再做例子. CREATE TABLE `t2` ( `id` int(11 ...