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是质数,所 ...
随机推荐
- Autoit3 获取WinForm下的ToolTip
相比Autohotkey,在我看来,Autoit最实用的就是对于WinForm Application的良好支持 然而,要想将鼠标放在WinForm的ToolTip上,简直无异于自己把自己举起来,故而 ...
- ResultSet can not re-read row data for column 1.
error:ResultSet can not re-read row data for column 1. 将数据类型改为varchar(max)后,查询数据错误 改正:将jdbc驱动改为jtds驱 ...
- pycharm快捷键及一些常用设置
pycharm快捷键及一些常用设置,有需要的朋友可以参考下. Alt+Enter 自动添加包 Ctrl+t SVN更新 Ctrl+k SVN提交 Ctrl + / 注释(取消注释)选择的行 Ctrl+ ...
- 百度地图多点路径加载以及调整页面js
$(document).ready(function () { /*用正则表达式获取url传递的地址参数,split后获得地址数组*/ bmap = new BMap.Map('mapcontaine ...
- 2>&1
经常关注linux脚本的人,一定看到过 2>&1 这样的用法,最初一定不明白其中的含义以及为什么是这样的一种组合.昨天偶然间再次看到了这个 2>&1 的写法,遂下决心搞明白 ...
- PHP语言中使用JSON和将json还原成数组
从5.2版本开始,PHP原生提供json_encode()和json_decode()函数,前者用于编码,后者用于解码. 一.json_encode() 1 2 3 4 <?php $arr = ...
- javascript 性能惰性加载2016.12.13
利用函数的惰性载入提高 javascript 代码性能 原文:利用函数的惰性载入提高javascript代码性能 作者:阿安 在 javascript 代码中,因为各浏览器之间的行为的差异,我们经常会 ...
- 推荐一篇 关于REST 和 SOAP区别的文章
写的很出色! https://www.ibm.com/developerworks/cn/webservices/0907_rest_soap/ 我的感觉就是REST针对的是资源,通过api的URL就 ...
- PCA 协方差矩阵特征向量的计算
人脸识别中矩阵的维数n>>样本个数m. 计算矩阵A的主成分,根据PCA的原理,就是计算A的协方差矩阵A'A的特征值和特征向量,但是A'A有可能比较大,所以根据A'A的大小,可以计算AA'或 ...
- JSFiddle
<script async src="//jsfiddle.net/980355088/k0u1qjm6/embed/"></script>