题目

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(树的点分治)的更多相关文章

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

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

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

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

  3. HDU 5977 Garden of Eden (树分治+状态压缩)

    题意:给一棵节点数为n,节点种类为k的无根树,问其中有多少种不同的简单路径,可以满足路径上经过所有k种类型的点? 析:对于路径,就是两类,第一种情况,就是跨过根结点,第二种是不跨过根结点,分别讨论就好 ...

  4. HDU5977 Garden of Eden 【FMT】【树形DP】

    题目大意:求有所有颜色的路径数. 题目分析:参考codeforces997C,先利用基的FMT的性质在$O(2^k)$做FMT,再利用只还原一位的特点在$O(2^k)$还原,不知道为什么网上都要点分治 ...

  5. hdu5977 Garden of Eden

    都不好意思写题解了 跑了4000多ms 纪念下自己A的第二题 (我还有一道freetour II wa20多发没A...呜呜呜 #include<bits/stdc++.h> using ...

  6. 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 ...

  7. Garden of Eden

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

  8. uva10001 Garden of Eden

    Cellular automata are mathematical idealizations of physical systems in which both space and time ar ...

  9. HDU4812 D Tree(树的点分治)

    题目大概说给一棵有点权的树,输出字典序最小的点对,使这两点间路径上点权的乘积模1000003的结果为k. 树的点分治搞了.因为是点权过根的两条路径的LCA会被重复统计,而注意到1000003是质数,所 ...

随机推荐

  1. 第3月第16天 fd_set 32 ACE_TP_Reactor

    1. #ifdef FD_SETSIZE #define __DARWIN_FD_SETSIZE FD_SETSIZE #else /* !FD_SETSIZE */ #define __DARWIN ...

  2. php 路径的理解

      当php文件用require方式包含了另外一个文件,这另外文件引用的图片是相对目录下的内容时,而该相对目录是指包含目录的文件的 -----index.php -----default 目录 --- ...

  3. centos7 编译php56

    编译安装php5.6 centos7环境 步骤: //下载php5.6 wget http://cn2.php.net/distributions/php-5.6.26.tar.bz2 //安装依赖 ...

  4. spark 官方文档(1)——提交应用程序

    Spark版本:1.6.2 spark-submit提供了在所有集群平台提交应用的统一接口,你不需要因为平台的迁移改变配置.Spark支持三种集群:Standalone.Apache Mesos和Ha ...

  5. Javascript模块化编程(三):require.js的用法

    Javascript模块化编程(三):require.js的用法 原文地址:http://www.ruanyifeng.com/blog/2012/11/require_js.html 作者: 阮一峰 ...

  6. php模拟http请求的方法

    我在这里终结了三种方法 第一种方法:fsockopen $flag = 0; $post = ''; $errno = ''; $errstr = ''; //要post的数据 $argv = arr ...

  7. python界面

    import easygui as g import sys while 1: g.msgbox("我一定要学会编程!","加油!") #choices = [ ...

  8. hdu1045 DFS

    #include<stdio.h> #include<string.h> int n; int maxx; ][]; ]={,-,,}; ]={,,,-}; ][][];//炮 ...

  9. ABAP 常见查询问题解决方法

    在ABAP 编程的时候会遇到查询单条语句的时候数能取对  但是条目数多了的话 会出现数不准确的问题   原因可能出现在查询使用了二分法查询方式  二分法查询下必须按排序的字段排序  还得按照排序的字段 ...

  10. PEtools

    // PETools.cpp : Defines the entry point for the console application.// #include "stdafx.h" ...