题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5977

题解:这题一看就知道是状压dp然后看了一下很像是点分治(有点明显)然后就是简单的点分治+状压dp,这里只要稍微改一下模版就行了。还有注意一下这里的cau状态枚举然后就没什么了

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const int M = 5e4 + ;
struct Edge {
int v , next;
}edge[M << ];
int head[M] , e , Size , root , n , k , a[M] , ssr;
ll ans;
bool vis[M];
void init() {
memset(head , - , sizeof(head));
memset(vis , false , sizeof(vis));
ans = ;
e = ;
ssr = (( << k) - );
}
void add(int u , int v) {
edge[e].v = v;
edge[e].next = head[u];
head[u] = e++;
}
int size[M] , mx[M];
ll Hash[];
void dfs_size(int u , int pre) {
size[u] = ;
mx[u] = ;
for(int i = head[u] ; i != - ; i = edge[i].next) {
int v = edge[i].v;
if(v == pre || vis[v]) continue;
dfs_size(v , u);
size[u] += size[v];
mx[u] = max(mx[u] , size[v]);
}
}
void dfs_root(int r , int u , int pre) {
mx[u] = max(mx[u] , size[r] - size[u]);
if(mx[u] < Size) Size = mx[u] , root = u;
for(int i = head[u] ; i != - ; i = edge[i].next) {
int v = edge[i].v;
if(v == pre || vis[v]) continue;
dfs_root(r , v , u);
}
}
void get_root(int u , int pre) {
dfs_size(u , pre);
dfs_root(u , u , pre);
}
int num , State[M];
void find_state(int u , int pre , int state) {
State[num++] = state;
for(int i = head[u] ; i != - ; i = edge[i].next) {
int v = edge[i].v;
if(vis[v] || v == pre) continue;
find_state(v , u , state | ( << a[v]));
}
}
ll cau(int u , int state) {
num = ;
find_state(u , - , state);
memset(Hash , , sizeof(Hash));
ll sum = ;
for(int i = ; i < num ; i++) Hash[State[i]]++;
for(int i = ; i < num ; i++) {
Hash[State[i]]--;
sum += Hash[ssr];//这里由于是枚举时0枚举不到所以先加上ssr^0.
for (int s0 = State[i]; s0; s0 = (s0 - ) & State[i])
sum += Hash[(( << k) - ) ^ s0];
Hash[State[i]]++;
}
return sum;
}
void dfs(int u) {
Size = n;
get_root(u , -);
ans += cau(root , ( << a[root]));
vis[root] = true;
int rt = root;
for(int i = head[root] ; ~i ; i = edge[i].next) {
int v = edge[i].v;
if(vis[v]) continue;
ans -= cau(v , ( << a[rt]) | ( << a[v]));
dfs(v);
}
}
int main() {
while(scanf("%d%d" , &n , &k) != EOF) {
init();
for(int i = ; i <= n ; i++) scanf("%d" , &a[i]) , a[i]--;
for(int i = ; i < n - ; i++) {
int u , v;
scanf("%d%d" , &u , &v);
add(u , v);
add(v , u);
}
if (k == ) {
printf("%lld\n", (ll)n * (ll)n);
continue;
}
dfs();
printf("%lld\n" , ans);
}
return ;
}

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 (树分治+状态压缩)

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

  3. HDU 6984 - Tree Planting(数据分治+状压 dp)

    题面传送门 傻逼卡常屑题/bs/bs,大概现场过得人比较少的原因就是它比较卡常罢(Fog 首先对于这样的题我们很难直接维护,不过注意到这个 \(n=300\) 给得很灵性,\(k\) 比较小和 \(k ...

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

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

  5. HDU 5977 Garden of Eden

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

  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-5977 Garden of Eden(树分治)

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

  9. HDU 3920Clear All of Them I(状压DP)

    HDU 3920   Clear All of Them I 题目是说有2n个敌人,现在可以发n枚炮弹,每枚炮弹可以(可以且仅可以)打两个敌人,每一枚炮弹的花费等于它所行进的距离,现在要消灭所有的敌人 ...

随机推荐

  1. codeforces 327 A Ciel and Dancing

    题目链接 给你一串只有0和1的数字,然后对某一区间的数翻转1次(0变1 1变0),只翻转一次而且不能不翻转,然后让你计算最多可能出现多少个1. 这里要注意很多细节 比如全为1,要求必须翻转,这时候我们 ...

  2. 实时同步lsyncd

    实时同步lsyncd 1 lsyncd 1.1 lsyncd 简介 Lsyncd使用文件系统事件接口(inotify或fsevents)来监视对本地文件和目录的更改.Lsyncd将这些事件整理几秒钟, ...

  3. Centos7 搭建owncloud云存储

    Centos7 搭建owncloud云存储 首先准备必要的软件和资料. 这里我已经整理好了: 百度云共享 不过最好还是自己去官网上下.这里只不过是提供了快捷方式. owncloud官网:https:/ ...

  4. 【JDK】JDK源码分析-AbstractQueuedSynchronizer(3)

    概述 前文「JDK源码分析-AbstractQueuedSynchronizer(2)」分析了 AQS 在独占模式下获取资源的流程,本文分析共享模式下的相关操作. 其实二者的操作大部分是类似的,理解了 ...

  5. 【Java笔记】【Java核心技术卷1】chapter3 D5运算符

    package chapter3; import java.math.*; //引入数学类 //枚举类型 enum Size{SMALL,MEDIUM,LARGE}; public class D5运 ...

  6. [NUnit] discover test finished: 0 found issue

    %Temp%\VisualStudioTestExplorerExtensions & restart visual studio

  7. 两个 github 账号混用,一个帐号提交错误

    问题是这样,之前有一个github帐号,因为注册邮箱的原因,不打算继续使用了,换了一个新的邮箱注册了一个新的邮箱帐号.新账号提交 就会出现下图的问题,但是原来帐号的库还是能正常提交.   方法1:添加 ...

  8. 使用python画3D线条

    """用于验证整体趋势正确性""" #!python3 #-*- coding:utf-8 -*- import matplotlib as ...

  9. manifest.json 解析--手机web app开发笔记(三-2)

    四.SDK配置和模块权限配置 SDK 就是 Software Development Kit 的缩写,中文意思就是“软件开发工具包”,也就是辅助开发某一类软件的相关文档.范例和工具的集合都可以叫做“S ...

  10. if else 深度优化

    一. if else表达式过于复杂 if ((condition1 && condition2 ) || ((condition2 || condition3) && ...