题意:给一棵节点数为n,节点种类为k的无根树,问其中有多少种不同的简单路径,可以满足路径上经过所有k种类型的点?

析:对于路径,就是两类,第一种情况,就是跨过根结点,第二种是不跨过根结点,分别讨论就好,由于结点比较大,所以采用分治来进行处理,优先选取重点作为划分的依据。

代码如下:

  1. #pragma comment(linker, "/STACK:1024000000,1024000000")
  2. #include <cstdio>
  3. #include <string>
  4. #include <cstdlib>
  5. #include <cmath>
  6. #include <iostream>
  7. #include <cstring>
  8. #include <set>
  9. #include <queue>
  10. #include <algorithm>
  11. #include <vector>
  12. #include <map>
  13. #include <cctype>
  14. #include <cmath>
  15. #include <stack>
  16. #include <sstream>
  17. #include <list>
  18. #include <assert.h>
  19. #define debug() puts("++++");
  20. #define gcd(a, b) __gcd(a, b)
  21. #define lson l,m,rt<<1
  22. #define rson m+1,r,rt<<1|1
  23. #define fi first
  24. #define se second
  25. #define pb push_back
  26. #define sqr(x) ((x)*(x))
  27. #define ms(a,b) memset(a, b, sizeof a)
  28. #define sz size()
  29. #define pu push_up
  30. #define pd push_down
  31. #define FOR(x,n) for(int i = (x); i < (n); ++i)
  32. #define freopenr freopen("in.txt", "r", stdin)
  33. #define freopenw freopen("out.txt", "w", stdout)
  34. using namespace std;
  35.  
  36. typedef long long LL;
  37. typedef unsigned long long ULL;
  38. typedef pair<int, int> P;
  39. const int INF = 0x3f3f3f3f;
  40. const double inf = 1e20;
  41. const double PI = acos(-1.0);
  42. const double eps = 1e-8;
  43. const int maxn = 50000 + 10;
  44. const LL mod = 1e9 + 7;
  45. const int dr[] = {-1, 0, 1, 0};
  46. const int dc[] = {0, 1, 0, -1};
  47. const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
  48. int n, m;
  49. const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  50. const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  51. inline bool is_in(int r, int c) {
  52. return r > 0 && r <= n && c > 0 && c <= m;
  53. }
  54. int all;
  55.  
  56. struct Edge{
  57. int to, next;
  58. };
  59.  
  60. Edge edge[maxn<<1];
  61. int head[maxn], cnt;
  62. int val[maxn];
  63.  
  64. void addEdge(int u, int v){
  65. edge[cnt].to = v;
  66. edge[cnt].next = head[u];
  67. head[u] = cnt++;
  68. }
  69.  
  70. int root, num, f[maxn];
  71. LL dp[1<<10];
  72. int sum[maxn];
  73. bool vis[maxn];
  74. LL ans;
  75.  
  76. void dfs_for_root(int u, int fa){
  77. sum[u] = 1; f[u] = 0;
  78. for(int i = head[u]; ~i; i = edge[i].next){
  79. int v = edge[i].to;
  80. if(v == fa || vis[v]) continue;
  81. dfs_for_root(v, u);
  82. sum[u] += sum[v];
  83. f[u] = max(f[u], sum[v]);
  84. }
  85. f[u] = max(f[u], num - sum[u]);
  86. if(f[root] > f[u]) root = u;
  87. }
  88.  
  89. void dfs_for_color(int u, int fa, int s){
  90. for(int i = head[u]; ~i; i = edge[i].next){
  91. int v = edge[i].to;
  92. if(v == fa || vis[v]) continue;
  93. ++dp[s|1<<val[v]];
  94. dfs_for_color(v, u, s|1<<val[v]);
  95. }
  96. }
  97.  
  98. LL solve(int u, int s){
  99. ms(dp, 0);
  100. ++dp[s];
  101. dfs_for_color(u, -1, s);
  102. LL ans = 0;
  103. for(int i = 0; i <= all; ++i){
  104. if(!dp[i]) continue;
  105. int tmp = 0;
  106. tmp += dp[all];
  107. for(int j = i; j; j = (j-1)&i)
  108. tmp += dp[all^j];
  109. ans += (LL)tmp * dp[i];
  110. }
  111. return ans;
  112. }
  113.  
  114. void dfs_for_ans(int u){
  115. ans += solve(u, 1<<val[u]);
  116. vis[u] = true;
  117. for(int i = head[u]; ~i; i = edge[i].next){
  118. int v = edge[i].to;
  119. if(vis[v]) continue;
  120. ans -= solve(v, 1<<val[u]|1<<val[v]);
  121. root = 0;
  122. f[0] = num = sum[v];
  123. dfs_for_root(v, u);
  124. dfs_for_ans(root);
  125. }
  126. }
  127.  
  128. int main(){
  129. while(scanf("%d %d", &n, &m) == 2){
  130. for(int i = 1; i <= n; ++i){
  131. scanf("%d", val+i);
  132. --val[i];
  133. }
  134. all = (1<<m) - 1;
  135. ms(head, -1); cnt = 0;
  136. for(int i = 1; i < n; ++i){
  137. int u, v;
  138. scanf("%d %d", &u, &v);
  139. addEdge(u, v);
  140. addEdge(v, u);
  141. }
  142. ms(vis, 0);
  143. root = 0; ans = 0LL;
  144. f[0] = num = n;
  145. dfs_for_root(1, -1);
  146. dfs_for_ans(root);
  147. printf("%I64d\n", ans);
  148. }
  149. return 0;
  150. }

  

HDU 5977 Garden of Eden (树分治+状态压缩)的更多相关文章

  1. HDU 5977 Garden of Eden(点分治求点对路径颜色数为K)

    Problem Description When God made the first man, he put him on a beautiful garden, the Garden of Ede ...

  2. hdu-5977 Garden of Eden(树分治)

    题目链接: Garden of Eden Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/ ...

  3. hdu 5977 Garden of Eden(点分治+状压)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5977 题解:这题一看就知道是状压dp然后看了一下很像是点分治(有点明显)然后就是简单的点分治+状压dp ...

  4. HDU 5977 Garden of Eden

    题解: 路径统计比较容易想到点分治和dp dp的话是f[i][j]表示以i为根,取了i,颜色数状态为j的方案数 但是转移这里如果暴力转移就是$(2^k)^2$了 于是用FWT优化集合或 另外http: ...

  5. HDU 5977 Garden of Eden (树形dp+快速沃尔什变换FWT)

    CGZ大佬提醒我,我要是再不更博客可就连一月一更的频率也没有了... emmm,正好做了一道有点意思的题,就拿出来充数吧=.= 题意 一棵树,有 $ n (n\leq50000) $ 个节点,每个点都 ...

  6. HDU - 5977 Garden of Eden (树形dp+容斥)

    题意:一棵树上有n(n<=50000)个结点,结点有k(k<=10)种颜色,问树上总共有多少条包含所有颜色的路径. 我最初的想法是树形状压dp,设dp[u][S]为以结点u为根的包含颜色集 ...

  7. HDU-5977 - Garden of Eden 点分治

    HDU - 5977 题意: 给定一颗树,问树上有多少节点对,节点对间包括了所有K种苹果. 思路: 点分治,对于每个节点记录从根节点到这个节点包含的所有情况,类似状压,因为K<=10.然后处理每 ...

  8. HDU 3605:Escape(最大流+状态压缩)

    http://acm.hdu.edu.cn/showproblem.php?pid=3605 题意:有n个人要去到m个星球上,这n个人每个人对m个星球有一个选择,即愿不愿意去,"Y" ...

  9. HDU 2809 God of War(DP + 状态压缩)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2809 题目大意:给出战神吕布的初始攻击力ATI.防御力DEF.生命值HP.每升一级增加的攻击力In_A ...

随机推荐

  1. 安装nagios检测hadoop

    Nagios是常用的系统监控工具,提供了很多基本服务的监控脚本,如HTTP,MYSQL等,同时具有不错的可扩展性,自己可定制针对特定参数的监控脚本以及报警的方式. 我现在有三台机器:192.168.0 ...

  2. 第十章 Secret & Configmap(下)

    10.4 ConfigMap Secret可以为Pod提供密码.Token.私钥等敏感数据:对于一些非敏感数据,比如一些配置信息,则可以用ConfigMap. configMap的使用方式与Secre ...

  3. 浅谈PHP面向对象编程(九、设计模式)

    9.0 设计模式 在编写程序时经常会遇到一此典型的问题或需要完成某种特定需求,设计模式就是针对这些问题和需求,在大量的实践中总结和理论化之后优选的代码结构编程风格,以及解决问题的思考方式. 设计模式就 ...

  4. CDH5.10.0 离线安装(共3节点) 转

    1.安装方式 CDH的离线部署安装,即Parcel包(推荐) 2.角色规划 三个节点对应的角色: 3.基本环境配置(在每个节点上都要配置) (1)关闭防火墙 #/etc/init.d/iptables ...

  5. ArraySort--冒泡排序、选择排序、插入排序工具类demo

    public class ArraySort { private long[] a; private int nElems; public ArraySort(int max){ a=new long ...

  6. 【转】Android开发笔记——圆角和边框们

    原文地址:http://blog.xianqu.org/2012/04/android-borders-and-radius-corners/ Android开发笔记——圆角和边框们 在做Androi ...

  7. g++ 4.4.7 template 没问题,前面应该程序问题!!

  8. Ubuntu TIP

    recovery进系统硬盘是挂载为“只读”的,要想改文件需要remount / 并且添加“w”(写权限). 进一次crub,再root进入 折腾几次似乎就可以编辑磁盘上的文件了

  9. Microsoft.Office.Core 引用以及 Microsoft.Office.Core.MsoTriState 的问题

    转自原文 xiaoanian, Microsoft.Office.Core 引用以及 Microsoft.Office.Core.MsoTriState 的问题 因为要做一个提取ppt文字的工程,第一 ...

  10. BurpSuite系列(十二)----User options模块(用户选择)

    一.简介   User options模块主要用来配置一些常用的选项. 二.模块说明 User options主要由4个模块组成: 1.Connections 连接 2.SSL 3.Display 4 ...