题目链接 Permutation

题目大意:给出n,和m个关系,每个关系为ai必须排在bi的前面,求符合要求的n的全排列的个数。

数据规模为n <= 40,m <= 20。 直接状压DP空间肯定是不够的。

考虑到m <= 20,说明每个连通块的大小不超过21。

那么我们分别对每个连通块求方案数,并且把不同的连通块的方案数组合起来即可。

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define rep(i, a, b) for (int i(a); i <= (b); ++i)
  6. #define dec(i, a, b) for (int i(a); i >= (b); --i)
  7.  
  8. typedef long long LL;
  9.  
  10. const LL mod = 1e9 + 7;
  11.  
  12. const int N = 105;
  13.  
  14. int n, m, s, cnt;
  15. int mp[N][N], a[N][N], b[N], col[N], pre[N];
  16. LL c[N][N], f[1 << 22], ans;
  17. vector <int> v[N];
  18.  
  19. void init(){
  20. c[0][0] = 1;
  21. rep(i, 1, N - 2){
  22. c[i][0] = 1;
  23. rep(j, 1, i - 1){
  24. c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
  25. c[i][j] %= mod;
  26.  
  27. }
  28. c[i][i] = 1;
  29. }
  30. }
  31.  
  32. void dfs(int x){
  33. col[x] = cnt;
  34. for (auto u : v[x]){
  35. if (col[u]) continue;
  36. dfs(u);
  37. }
  38. }
  39.  
  40. int main(){
  41.  
  42. init();
  43.  
  44. while (~scanf("%d%d", &n, &m)){
  45.  
  46. rep(i, 0, n + 1) v[i].clear();
  47. memset(mp, 0, sizeof mp);
  48. memset(col, 0, sizeof col);
  49. rep(i, 1, m){
  50. int x, y;
  51. scanf("%d%d", &x, &y);
  52. v[x].push_back(y);
  53. v[y].push_back(x);
  54. mp[x][y] = 1;
  55. mp[y][x] = -1;
  56. }
  57.  
  58. cnt = 0;
  59. rep(i, 1, n) if (!col[i]) ++cnt, dfs(i);
  60.  
  61. memset(b, 0, sizeof b);
  62. rep(i, 1, n) a[col[i]][b[col[i]]++] = i;
  63.  
  64. s = n;
  65. ans = 1;
  66.  
  67. rep(i, 1, cnt){
  68. int maxS = (1 << b[i]) - 1;
  69. rep(j, 0, maxS + 2) f[j] = 0;
  70. f[0] = 1LL;
  71. memset(pre, 0, sizeof pre);
  72. rep(j, 0, b[i] - 1){
  73. rep(k, 0, b[i] - 1) if (j ^ k){
  74. if (mp[a[i][j]][a[i][k]] == 1) pre[k] |= (1 << j);
  75. }
  76. }
  77.  
  78. rep(S, 0, maxS) if (f[S] > 0){
  79. rep(j, 0, b[i] - 1){
  80. if (((S & pre[j]) == pre[j]) && !(S & (1 << j))){
  81. f[S | (1 << j)] += f[S];
  82. f[S | (1 << j)] %= mod;
  83. }
  84. }
  85. }
  86.  
  87. ans = ans * f[(1 << b[i]) - 1] % mod * c[s][b[i]] % mod;
  88. s -= b[i];
  89. }
  90.  
  91. printf("%lld\n", ans);
  92. }
  93. return 0;
  94. }

HDU 4917 Permutation(拓扑排序 + 状压DP + 组合数)的更多相关文章

  1. HDU 4917 Permutation 拓扑排序的计数

    题意: 一个有n个数的排列,给你一些位置上数字的大小关系.求合法的排列有多少种. 思路: 数字的大小关系可以看做是一条有向边,这样以每个位置当点,就可以把整个排列当做一张有向图.而且题目保证有解,所以 ...

  2. 【XSY3042】石像 拓扑排序 状压DP 洲阁筛

    题目大意 有 \(n\) 个整数 \(a_1,a_2,\ldots,a_n\),每个数的范围是 \([1,m]\).还有 \(k\) 个限制,每个限制 \(x_i,y_i\) 表示 \(a_{x_i} ...

  3. HDU 6149 Valley Numer II 状压DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6149 题意:中文题目 解法:状压DP,dp[i][j]代表前i个低点,当前高点状态为j的方案数,然后枚 ...

  4. HDU 5434 Peace small elephant 状压dp+矩阵快速幂

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant  Accepts: 38  Submissions: ...

  5. HDU 1074 Doing Homework(状压DP)

    第一次写博客ORZ…… http://acm.split.hdu.edu.cn/showproblem.php?pid=1074 http://acm.hdu.edu.cn/showproblem.p ...

  6. HDU 4906 Our happy ending (状压DP)

    HDU 4906 Our happy ending pid=4906" style="">题目链接 题意:给定n个数字,每一个数字能够是0-l,要选当中一些数字.然 ...

  7. HDU 1074 Doing Homework (状压dp)

    题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...

  8. HDU 4568 Hunter 最短路+状压DP

    题意:给一个n*m的格子,格子中有一些数,如果是正整数则为到此格子的花费,如果为-1表示此格子不可到,现在给k个宝藏的地点(k<=13),求一个人从边界外一点进入整个棋盘,然后拿走所有能拿走的宝 ...

  9. HDU 1074 Doing Homework【状压DP】

    Doing Homework Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he ...

随机推荐

  1. quartz测试类

    package demo.mytest; import java.text.ParseException; import org.quartz.CronTrigger;import org.quart ...

  2. 2018 CCF NOIP提高组&&普及组答案

    答案: 这是今年的答案大家觉得能进到复赛吗? 下一篇文章将会为大家推荐我自己出的复赛题!!!

  3. (16)zabbix history trends历史与趋势数据详解

    1. 保留历史数据 我们可以通过如下方式来设置保留数据的时长:监控项(item)配置里匹配更新监控项(item)设置Housekeeper tasksHousekeeper会定期删除过期的数据.如果数 ...

  4. DateFormat的format()方法线程不安全的问题分析

    最近看到<侦探剧场:堆内存神秘溢出事件>https://my.oschina.net/u/2368090/blog/1628720,于是自己也想测试了解一下DateFormat的多线程安全 ...

  5. struct 区别 在C 和C++ 中

    C语言中:   Struct是用户自定义数据类型(UDT).   C++语言中:   Struct是抽象数据类型(ADT),支持成员函数的定义.       在C++中,struct的成员的默认访问说 ...

  6. Sublime安装与配置

    1.到官网下载Sublime https://www.sublimetext.com/ 2.安装时选择添加到右键菜单 Add to explorer context menu 3.安装插件 菜单 to ...

  7. C语言文件操作 FILE结构体

    内存中的数据都是暂时的,当程序结束时,它们都将丢失.为了永久性的保存大量的数据,C语言提供了对文件的操作. 1.文件和流 C将每个文件简单地作为顺序字节流(如下图).每个文件用文件结束符结束,或者在特 ...

  8. Html 前端jinjia2 & ajax

    本章内容: jinja2 Ajax中的if语句 参考文档 html可以参照学习:w3school bootstrap学习:bootstrap 综合类学习网站:runoob jinja2学习网站:jin ...

  9. IPy模块--IP地址处理

    Python之实用的IP地址处理模块IPy 实用的IP地址处理模块IPy 在IP地址规划中,涉及到计算大量的IP地址,包括网段.网络掩码.广播地址.子网数.IP类型等 别担心,Ipy模块拯救你.Ipy ...

  10. Python内置函数7

    Python内置函数7 1.propertypython内置的一个装饰器可参考https://blog.csdn.net/u013205877/article/details/77804137 2.q ...