题意:给一个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种方式)的更多相关文章

  1. BZOJ 1369 Gem - 树型dp

    传送门 题目大意: 给一棵树上每个点一个正权值,要求父子的权值不同,问该树的最小权值和是多少. 题目分析: 证不出来最少染色数,那就直接信仰用20来dp吧:dp[u][i]表示u节点权值赋为i时u子树 ...

  2. 选课 - 树型DP(孩子兄弟建树法)

    题目描述 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了 N(N<300)门的选修课程,每个学生可选课程的数量 M 是给定的.学生选修了这M门课并考核通 ...

  3. BZOJ 1564 :[NOI2009]二叉查找树(树型DP)

    二叉查找树 [题目描述] 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左儿子结点的数据值大,而比它右儿子结点的数据值小. 另一方面,这棵查找树中每个结点都有一个权值,每个结 ...

  4. BZOJ 2286 消耗战 - 虚树 + 树型dp

    传送门 题目大意: 每次给出k个特殊点,回答将这些特殊点与根节点断开至少需要多少代价. 题目分析: 虚树入门 + 树型dp: 刚刚学习完虚树(好文),就来这道入门题签个到. 虚树就是将树中的一些关键点 ...

  5. BZOJ 1509 逃学的小孩 - 树型dp

    传送门 题目大意: 在一棵树中, 每条边都有一个长度值, 现要求在树中选择 3 个点 X.Y. Z , 满足 X 到 Y 的距离不大于 X 到 Z 的距离, 且 X 到 Y 的距离与 Y 到 Z 的距 ...

  6. BZOJ 1864 三色二叉树 - 树型dp

    传送门 题目大意: 给一颗二叉树染色红绿蓝,父亲和儿子颜色必须不同,两个儿子颜色必须不同,问最多和最少能染多少个绿色的. 题目分析: 裸的树型dp:\(dp[u][col][type]\)表示u节点染 ...

  7. POJ 3342 - Party at Hali-Bula 树型DP+最优解唯一性判断

    好久没写树型dp了...以前都是先找到叶子节点.用队列维护来做的...这次学着vector动态数组+DFS回朔的方法..感觉思路更加的清晰... 关于题目的第一问...能邀请到的最多人数..so ea ...

  8. 洛谷P3354 Riv河流 [IOI2005] 树型dp

    正解:树型dp 解题报告: 传送门! 简要题意:有棵树,每个节点有个权值w,要求选k个节点,最大化∑dis*w,其中如果某个节点到根的路径上选了别的节点,dis指的是到达那个节点的距离 首先这个一看就 ...

  9. 【POJ 3140】 Contestants Division(树型dp)

    id=3140">[POJ 3140] Contestants Division(树型dp) Time Limit: 2000MS   Memory Limit: 65536K Tot ...

随机推荐

  1. Python找对称数——纪念第一次自主编写代码

    2021-01-17 题目: [问题描述]已知10个四位数输出所有对称数及个数 n,例如1221.2332都是对称数[输入形式]10个四位数,以空格分隔开[输出形式]输入的四位数中的所有对称数,对称数 ...

  2. .NET探索平台条件编译

    前言 今天偶然机会,翻了一下大学期间的书籍<C程序设计>,好吧,当我翻着翻着,翻到了符号常量(#define指令)中,是啊,这是一个预处理器指令,记得在Magicodes.IE中针对平台选 ...

  3. MongoDB导出导入功能

    导出脚本: mongo_export.sh !#/bin/bash mongoexport -h x.x.x.x  --port 27017 -d database -c collection  -q ...

  4. netstat -an|awk '/^tcp/ {++s[$NF]} END {for( a in s) {print a,s[a]}}'

    监控tcp连接情况 netstat  -an|awk '/^tcp/ {++s[$NF]} END {for( a in s) {print  a,s[a]}}'

  5. 【EXP】exp-00091解决办法

    如果遇到exp的话一般都是因为字符集的问题 解决办法: 1.在oracle中查看数据库的字符集 SQL> select userenv('language') from dual; USEREN ...

  6. VS2019项目docker启动且访问SQLSERVER数据库配置

    VS2019编译.调试的Blazor纯前台项目,使用控制台启动,去连接纯后台的API项目,使用docker启动,并且通过EFCore访问SQLSERVER数据库,有几个地方需要修改配置: 一.前台连后 ...

  7. uni-app 微信小程序 picker 三级联动

    之前做过一个picker的三级联动功能,这里分享代码给大家 具体代码: // An highlighted block <template> <view> <picker ...

  8. uni-app开发经验分享十: 封装request请求

    http.js //封装requset,uploadFile和downloadFile请求,新增get和post请求方法 let http = { 'setBaseUrl': (url) => ...

  9. MySQL全面瓦解21(番外):一次深夜优化亿级数据分页的奇妙经历

    背景 1月22号晚上10点半,下班后愉快的坐在在回家的地铁上,心里想着周末的生活怎么安排. 突然电话响了起来,一看是我们的一个开发同学,顿时紧张了起来,本周的版本已经发布过了,这时候打电话一般来说是线 ...

  10. 前端中的script标签

    script标签中的重要属性! . 浏览器解析行内脚本的方式决定了它在看到字符串时,会将其当成结束的 标签.想避免这个问题,只需要转义字符"\" ①即可: 要包含外部文件中的 Ja ...