HDU5977 Garden of Eden(树的点分治)
题目
Source
http://acm.hdu.edu.cn/showproblem.php?pid=5977
Description
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
分析
题目大概说一棵树,各个结点都有一个数字(<=k),然后问有几条路径使得路径上所有结点包含了1到k的所有数字。
路径,自然想到树分治解决,因为任何一条路径都在以某个点为根的子树中且过那条根的链。
- 考虑cnt[S]记录已经统计获得的数字集合为S的路径数量。。
- 不过这样会发现,新的路径信息与其合并更新答案时,还要枚举它的补集以及补集的超集,这时间复杂度不太好。。
- 所以直接cnt[S]表示已经统计获得的数字集合为S以及S的超集的路径数量。。
- 现在问题是新的路径信息如何合并到cnt[S]中,其实只要枚举所有新的路径信息再枚举所有集合状态就OK了,时间复杂度由主定理可知是$O(nlogn2^k)$。。简单粗暴就过了。。
另外。。注意路径的起点和终点是可以一样的。。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 50010 struct Edge{
int v,next;
}edge[MAXN<<1];
int NE,head[MAXN];
void addEdge(int u,int v){
edge[NE].v=v; edge[NE].next=head[u];
head[u]=NE++;
} bool vis[MAXN];
int size[MAXN];
void getsize(int u,int fa){
size[u]=1;
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(vis[v] || v==fa) continue;
getsize(v,u);
size[u]+=size[v];
}
}
int mini,cen;
void getcen(int u,int fa,int &tot){
int res=tot-size[u];
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(vis[v] || v==fa) continue;
res=max(res,size[v]);
getcen(v,u,tot);
}
if(res<mini){
mini=res;
cen=u;
}
}
int getcen(int u){
getsize(u,u);
mini=INF;
getcen(u,u,size[u]);
return cen;
} long long cnt[1024];
int rec[MAXN],rn; int type,val[MAXN]; long long ans; void conqur_dfs(int u,int fa,int s){
ans+=cnt[(~s)&((1<<type)-1)];
rec[rn++]=s;
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(fa==v || vis[v]) continue;
conqur_dfs(v,u,s|(1<<val[v]));
}
}
void conqur(int u){
memset(cnt,0,sizeof(cnt));
cnt[0]=1;
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(vis[v]) continue;
rn=0;
conqur_dfs(v,v,(1<<val[u])|(1<<val[v]));
for(int j=0; j<rn; ++j){
for(int k=0; k<(1<<type); ++k){
if((rec[j]|k)==rec[j]) ++cnt[k];
}
}
}
}
void divide(int u){
u=getcen(u);
vis[u]=1;
conqur(u);
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(vis[v]) continue;
divide(v);
}
} int main(){
int n;
while(~scanf("%d%d",&n,&type)){
for(int i=1; i<=n; ++i){
scanf("%d",val+i);
--val[i];
}
NE=0;
memset(head,-1,sizeof(head));
int a,b;
for(int i=1; i<n; ++i){
scanf("%d%d",&a,&b);
addEdge(a,b);
addEdge(b,a);
}
memset(vis,0,sizeof(vis));
ans=0;
divide(1);
ans*=2;
if(type==1) ans+=n;
printf("%lld\n",ans);
}
return 0;
}
HDU5977 Garden of Eden(树的点分治)的更多相关文章
- hdu-5977 Garden of Eden(树分治)
题目链接: Garden of Eden Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/ ...
- HDU-5977 - Garden of Eden 点分治
HDU - 5977 题意: 给定一颗树,问树上有多少节点对,节点对间包括了所有K种苹果. 思路: 点分治,对于每个节点记录从根节点到这个节点包含的所有情况,类似状压,因为K<=10.然后处理每 ...
- HDU 5977 Garden of Eden (树分治+状态压缩)
题意:给一棵节点数为n,节点种类为k的无根树,问其中有多少种不同的简单路径,可以满足路径上经过所有k种类型的点? 析:对于路径,就是两类,第一种情况,就是跨过根结点,第二种是不跨过根结点,分别讨论就好 ...
- HDU5977 Garden of Eden 【FMT】【树形DP】
题目大意:求有所有颜色的路径数. 题目分析:参考codeforces997C,先利用基的FMT的性质在$O(2^k)$做FMT,再利用只还原一位的特点在$O(2^k)$还原,不知道为什么网上都要点分治 ...
- hdu5977 Garden of Eden
都不好意思写题解了 跑了4000多ms 纪念下自己A的第二题 (我还有一道freetour II wa20多发没A...呜呜呜 #include<bits/stdc++.h> using ...
- 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 ...
- Garden of Eden
Garden of Eden Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- uva10001 Garden of Eden
Cellular automata are mathematical idealizations of physical systems in which both space and time ar ...
- HDU4812 D Tree(树的点分治)
题目大概说给一棵有点权的树,输出字典序最小的点对,使这两点间路径上点权的乘积模1000003的结果为k. 树的点分治搞了.因为是点权过根的两条路径的LCA会被重复统计,而注意到1000003是质数,所 ...
随机推荐
- cookie (储存在用户本地终端上的数据)
Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份.进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密).定义于 RFC2109 和 2965 中的都已废弃 ...
- easyui Datagrid查询报错Uncaught TypeError:Cannot read property 'length' of undefined
1.问题描述 easyui中datagrid执行loadData方法出现如下异常:Cannot read property 'length' of undefined 2.一开始怀疑是js或者页面的问 ...
- QSS的应用
1.在同一级别的widget中,如果指定widget有设置样式表,则在qss对该样式表的设置无效,对比验证: (StatusWidget未设置widget样式--运行截图) (StatusWidget ...
- CapsLock与ctrl的键位修改
windows下修改方式: linux下修改方式: 在用户目录下新建文档命名为keychange.sh 编辑以下内容: remove Lock = Caps_Lock remove Control = ...
- 总结初用erlang 时的遇到一些问题
算起来接触erlang 三个多月快四个月来,期间从零开始看书写erlang代码.修改RabbitMQ.业务开发.系统调优,总算是有点入门了. 最难受的是边学边修改RabbitMQ,开始真心的看不懂,不 ...
- 《转载》Spring MVC之@RequestParam @RequestBody @RequestHeader 等详解
引言: 接上一篇文章,对@RequestMapping进行地址映射讲解之后,该篇主要讲解request 数据到handler method 参数数据的绑定所用到的注解和什么情形下使用: 简介: han ...
- PSD文件在MAC上和在WINDOWS上的大小有本质区别
因为偷懒在MAC上的美工,发我的PSD文件,我就直接在上面做了= =后来不知道为什么无论我怎么合并图层.PSD的大小永远都是107M....然后忍无可忍重新画就从107M变成2M.....MAC为什么 ...
- 修改Glassfish默认密码,并允许远程登录
修改默认密码 1.打开命令提示窗口,进入 glassfish/bin 目录: 2.输入命令 asadmin 进入管理模式: 接着输入: change-admin-password 注意默认密码为空,要 ...
- int ,long , long long类型的范围
int ,long , long long类型的范围 unsigned - - unsigned - - unsigned __int64的最大值: __int64的最小值:- unsigned __ ...
- struts2笔记(3)
关于回显: 如果是int型,默认就会回显为0,如果不想让回显,则Integer就好 //**************************************声明式验证************* ...