题干:

When God made the first man, he put him on a beautiful garden, the Garden of Eden. Here Adam lived with all animals. God gave Adam eternal life. But Adam was lonely in the garden, so God made Eve. When Adam was asleep one night, God took a rib from him and made Eve beside him. God said to them, “here in the Garden, you can do everything, but you cannot eat apples from the tree of knowledge.” 
One day, Satan came to the garden. He changed into a snake and went to live in the tree of knowledge. When Eve came near the tree someday, the snake called her. He gave her an apple and persuaded her to eat it. Eve took a bite, and then she took the apple to Adam. And Adam ate it, too. Finally, they were driven out by God and began a hard journey of life. 
The above is the story we are familiar with. But we imagine that Satan love knowledge more than doing bad things. In Garden of Eden, the tree of knowledge has n apples, and there are k varieties of apples on the tree. Satan wants to eat all kinds of apple to gets all kinds of knowledge.So he chooses a starting point in the tree,and starts walking along the edges of tree,and finally stops at a point in the tree(starting point and end point may be same).The same point can only be passed once.He wants to know how many different kinds of schemes he can choose to eat all kinds of apple. Two schemes are different when their starting points are different or ending points are different.

Input

There are several cases.Process till end of input. 
For each case, the first line contains two integers n and k, denoting the number of apples on the tree and number of kinds of apple on the tree respectively. 
The second line contains n integers meaning the type of the i-th apple. Types are represented by integers between 1 and k . 
Each of the following n-1 lines contains two integers u and v,meaning there is one edge between u and v.1≤n≤50000, 1≤k≤10

Output

For each case output your answer on a single line.

Sample Input

3 2
1 2 2
1 2
1 3

Sample Output

6

题目大意:

给定N个节点的树,每个节点有颜色,共k种颜色,求树上所有满足从i到j所经过的点包含了所有颜色的点对,(i,j)和(j,i)视为不同且i可以等于j。(N<=5e4,k<=10)

解题报告:

k=10,考虑状态压缩,最多可以(1<<(10)-1)种状态,利用树分治保存每个点到节点的路径状态。比求路径之和等于k的点对要简单,因为不需要容斥,可以用蓝书上第一种方法去求(按照子树顺序分别处理),但是细节还是要注意,比如当前的根节点别被统计多次了,且别忘了从根节点当其中一个端点,开始往下一条链的那种情况,其实这种情况是不需要特判的,只需要在做当前根节点上的所有工作之前,让cnt[(1<<col[cur])]++即可。

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define FF first
#define SS second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 1e5 + 5;
int col[MAX],head[MAX],tot,size[MAX],n,k;
struct Node {int to,ne;
} e[MAX<<1];
bool vis[MAX];
int up,cnt[MAX],tmp[MAX];
void add(int u,int v) {e[++tot].to = v;e[tot].ne=head[u];head[u]=tot;
}
ll ans;
int rt,all,son[MAX];
//getRoot调用之前必须先rt=0;
void getRoot(int cur,int fa) {size[cur]=1;son[cur]=0;for(int i = head[cur]; ~i; i = e[i].ne) {int v = e[i].to;if(v == fa || vis[v]) continue;getRoot(v,cur); size[cur] += size[v];son[cur] = max(son[cur],size[v]);}son[cur] = max(son[cur],all - size[cur]);//注意这里的all指的就是当前子树的节点个数 if(son[rt] == 0 || son[rt] > son[cur]) rt = cur;//值小,则更新根节点
}
void gx(int cur,int fa) {size[cur]=1;for(int i = head[cur]; ~i; i = e[i].ne) {int v = e[i].to;if(v == fa || vis[v]) continue;gx(v,cur); size[cur] += size[v];}
}
void get(int cur,int fa,int sta) {tmp[sta]++;
//  if(sta == (up-1)) ans++;for(int bit = 0; bit<up; bit++) {if((bit|sta) == (up-1)) ans += cnt[bit];} for(int i = head[cur]; ~i; i = e[i].ne) {int v = e[i].to;if(v == fa || vis[v]) continue;get(v,cur,sta|(1<<col[v]));}
}
void cal(int cur) {for(int i = 0; i<up; i++) cnt[i] = 0;cnt[(1<<col[cur])]++;
//  get(cur,0,1<<col[cur]);//注意这里不能等效处理,因为cur的子节点需要特殊处理,因为我们需要一个子树一个子树的处理。 for(int i = head[cur]; ~i; i = e[i].ne) {int v = e[i].to; if(vis[v]) continue;for(int sta = 0; sta<up; sta++) tmp[sta]=0;
//      tmp[(1<<col[cur])]++;//不能在这里加!不然就重复了! get(v,cur,(1<<col[cur]) | (1<<col[v]));for(int sta = 0; sta<up; sta++) cnt[sta] += tmp[sta];}
}
void dfs(int cur) {rt=0; getRoot(cur,0); cur=rt;  vis[cur]=1; gx(cur,0);cal(cur);for(int i = head[cur]; ~i; i = e[i].ne) {int v = e[i].to;if(vis[v]) continue;all = size[v];  dfs(v); }
}
int main()
{while(~scanf("%d%d",&n,&k)) {tot=0; up = 1<<k; ans = 0;for(int i = 1; i<=n; i++) head[i] = -1,vis[i]=size[i]=0;for(int i = 1; i<=n; i++) scanf("%d",col+i),col[i]--; for(int u,v,i = 1; i<=n-1; i++) scanf("%d%d",&u,&v),add(u,v),add(v,u);if(k == 1) {printf("%lld\n",1LL*n*(n-1)+n);continue;}all=n; dfs(1);printf("%lld\n",ans*2); } return 0 ;
}

【HDU - 5977】Garden of Eden(树分治)相关推荐

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

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

  2. 树的点分治(HDU 5977 2016ICPC大连 G: Garden of Eden)

    题意: 有一棵n个节点的数,每个点都有一个值(1<=pi<=k),问有多少条路径满足包含1到k中的所有数字 可以想到状压+树形dp,但是开dp[50005][1025]的数组内存占用过大, ...

  3. HDU 5664 Lady CA and the graph 二分,树分治

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5664 题意:有一个有n个点的树(2<=n<=50,000),链(a,b)被称作折链,当且仅 ...

  4. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

  5. bzoj 4025 二分图——线段树分治+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4025 线段树分治,用 LCT 维护链的长度即可.不过很慢. 正常(更快)的方法应该是线段树分 ...

  6. 线段树分治 ---- F. Extending Set of Points(线段树分治 + 可撤销并查集)

    题目链接 题目大意: 你有个点集合SSS,每次往集合里面加点或者删点(如果要加的点出现过),如果(x1,y1),(x2,y1),(x1,y2),(x2,y2)(x1,y1),(x2,y1),(x1,y ...

  7. 线段树分治 ---- CF1217F - Forced Online Queries Problem(假离线 可撤销并查集 + 线段树分治)详解

    题目链接 题目大意 解题思路: 我一开始想到可以用可撤销并查集去维护这种删边加边的操作,但是有个缺点是每次撤销都有把后面的边全部撤销复度是O(n2)O(n^2)O(n2) 首先我们考虑这种动态加边删边 ...

  8. [ACM] hdu 1671 Phone List (字典树)

    [ACM] hdu 1671 Phone List (字典树) Phone List Problem Description Given a list of phone numbers, determ ...

  9. POJ 1741 树分治

    题目链接[http://poj.org/problem?id=1741] 题意: 给出一颗树,然后寻找点对(u,v)&&dis[u][v] < k的对数. 题解: 这是一个很经典 ...

最新文章

  1. Modelsim仿真如何查看内部信号
  2. 手持移动端特殊链接:打电话,发短信,发邮件
  3. 一个项目中既有移动端,同时也有PC端的代码,并且 他们的代码分开写的,那么如何实现在手机跳转手机页面,pc点击跳转pc页面...
  4. 阿里云服务器怎么去掉tomcat的8080端口
  5. PyTorch基础(part8)--LSTM
  6. c语言编程经典实例利润,C语言经典编程实例100题解答
  7. Mysql数据库优化技术之配置篇、索引篇 ( 必看 必看 转)
  8. 计算机网络学习(六)—网络层概述以及相关习题
  9. linux编写周期性计划任务,linux任务计划及周期性任务计划
  10. Dinic最大流(bzoj 2756: [SCOI2012]奇怪的游戏)
  11. NB-IoT未来发展,主要是靠什么驱动的?
  12. Ubuntu 20:Cadence IC615集成HSPICE
  13. html+css+javascript满屏雪花爱心520表白网站 (含音乐)520告白/七夕情人节/生日礼物/程序员表白必备
  14. 计算机的管理员关机命令,电脑自动关机命令是什么?怎么用
  15. 51JOB:根据HR处理简历的一般流程,简历投递后会有如下几种状态出现
  16. 计算机专业梦想作文,我的理想是电脑工程师作文
  17. 第一周:数据的描述性统计
  18. 聚合支付介绍—简单明了一目了然
  19. 如何在集群上运行Shark
  20. 什么是 Toll-Free Bridging

热门文章

  1. 细学PHP 14 mysql-4
  2. svn在linux下的使用(svn命令行)ubuntu 删除 新增 添加 提交 状态查询 恢复
  3. 【转】excel表格导出集锦repeater实用,和普通用法
  4. 675. Cut Off Trees for Golf Event
  5. 力扣:组合总和 II DFS剪枝
  6. 学PHP的嫌弃什么歌,抖音再见了互相嫌弃的老同学是什么歌
  7. 拆包--缓冲区查找包头及包尾偏移
  8. linux 下查看程序依赖的库
  9. Linux内核的时钟中断
  10. Android判断view在屏幕可见,如何检查TextView是否在Android可见屏幕内