题意:给一个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种方式)相关推荐

  1. 其他OJ 树型DP 选课

    在朱全民的PPT介绍的一个树型DP经典题,<选课>,中文题目,不结束 找了很久找到了可以提交的OJ,重庆八中 http://www.cqoi.net:2012/JudgeOnline/pr ...

  2. 【树型DP】加分二叉树

    问题 b: [树型DP]加分二叉树 时间限制: 1 Sec  内存限制: 64 MB 提交: 8  解决: 6 [提交] [状态] [讨论版] [命题人:admin] 题目描述 科技忽略了过程就是魔法 ...

  3. 二叉苹果树(树型DP+背包)

    二叉苹果树 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点).这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号 ...

  4. POJ3342 Party at Hali-Bula(树型DP求最大独立集+唯一解判断)

    题意: 公司参加聚会,要求员工不能和他的上司同时参加,求最多能参加几个人并且判断解是否唯一. 要点: 树型DP的经典题,用dp[u][1]表示选取u的最大值,dp[u][0]表示不选取u的最大值,容易 ...

  5. 虚树+树型DP SDOI2011消耗战

    <虚树+树型DP> SDOI2011消耗战 #include <iostream> #include <cstdio> #include <cstring&g ...

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

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

  7. hihocoder 1479 三等分 树型dp

    描述 小Hi最近参加了一场比赛,这场比赛中小Hi被要求将一棵树拆成3份,使得每一份中所有节点的权值和相等. 比赛结束后,小Hi发现虽然大家得到的树几乎一模一样,但是每个人的方法都有所不同.于是小Hi希 ...

  8. 蓝桥杯:生命之树【树型dp】

    之前本菜还没学树型dp的时候,下意识地认为这个东西很难,感觉这个东西结合了搜索+dp这两座算法界的大山必定很难,但万万没想到啊,这个东西很像我之前讲的记忆化搜索,甚至我认为,记忆化搜索的一个作用就是将 ...

  9. 【树型DP】BZOJ1564 二叉查找树(noi2009)

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

最新文章

  1. [Vue CLI 3] 插件开发之 registerCommand 到底做了什么
  2. Swift3.0语言教程获得一个公共的前缀
  3. 【转】 Pro Android学习笔记(二九):用户界面和控制(17):include和merge
  4. 「拨云见日」英特尔揭秘短视频背后的二三事
  5. php里h和h的区别吗,编码h264h和h264b有什么区别
  6. WebBrowser中html元素如何触发winform事件
  7. Bash 入门教程10-处理用户输入
  8. 什么情况下不应该使用深度学习?
  9. HTML5-Video(视屏播放)
  10. 异步任务+JSON解析+ListView分页
  11. 阿里、腾讯、知乎裁员 那些被裁的程序员怎么办?
  12. 最后采用加权求和的方式得到样本的_一种婴幼儿视力自动检测方法与流程
  13. java毕业设计软件源代码SSM酒店管理系统|旅店管理
  14. OA、CRM、ERP、BPM系统
  15. mysql主从配置干什么_mysql主从配置之slave_exec_mode=IDEMPOTENT详解
  16. 鲲鹏、昇腾、欧拉——计算产业的矩阵已足够宽广
  17. 速达财务软件未能连接服务器,速达3000财务软件使用常见问题
  18. AJAX-客户端服务器端通信
  19. 基尔霍夫(kirchhoff)矩阵树定理
  20. Virtual Box安装Ubuntu

热门文章

  1. POJ 2112 二分+最大流
  2. awk编程基本使用示例
  3. 【Java】关于Java编程软件idea快捷键的使用
  4. Linux服务器添加SVN用户
  5. Linux目录下有剩余空间,但无法写入数据
  6. Jmeter基础使用
  7. 从高排到低变成小楼梯儿歌_幼儿早教三字儿歌,帮助宝宝启蒙学说话
  8. raster | R语言中的空间栅格对象及其基本处理方法(Ⅰ)
  9. 广西大学计算机英语复试的内容,广西大学计算机专业的研究生复试时
  10. 劝你们,千千千万不要当一个程序员!!!!!!