CodeForces - 1118 F2 Tree Cutting
题解:
先注意到一定存在k种颜色,切成k个块, 然后要求每个块内的颜色都一样,所以可以发现同一种颜色一定在同一个块内,故任意2个相同颜色的最短路劲上的点的颜色都是该颜色。
我们可以先把任意相同颜色点对的路径上的点的颜色都染成这个颜色。 如果发现存在一个点是已经有颜色的话,那么答案一定为0。
至于怎么颜色, 我们可以暴力往上跑,然后压缩路径,和并查集一样的道理,路过的点都染色且压缩。
这样就完成了第一部分的处理,接下来就是树DP了。
定义dp[ u ][ 0 ] 的含义是 以u为根的子树,且u还未被划入任意一种颜色的方案数。
dp[ u ][ 1 ] 的含义是 以u为根的子树,且u已被划入任意一种颜色的方案数。
那么对于有颜色的点来说,
dp[u][0] = 0;

对于没有颜色的点来说:


代码:
/*
code by: zstu wxk
time: 2019/03/02
Tags: 树DP
Problem Link: http://codeforces.com/contest/1118/problem/F2
Solve: https://www.cnblogs.com/MingSD/p/10462228.html
*/
#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL _INF = 0xc0c0c0c0c0c0c0c0;
const LL mod = ;
const int N = 3e5 + ;
int n, k, deep[N], fa[N], col[N];
vector<int> vc[N], e1[N];
void dfs(int o, int u){
deep[u] = deep[o] + ;
fa[u] = o;
for(int v : e1[u]){
if(v == o) continue;
dfs(u, v);
}
}
bool Link(int u, int v, int k){
int tu = u, tv = v;
while(u != v){
if(deep[u] > deep[v]){
u = fa[u];
if(col[u] && col[u] != k) return false;
col[u] = k;
}
else {
v = fa[v];
if(col[v] && col[v] != k) return false;
col[v] = k;
}
}
while(tu != u){
int tt = fa[tu];
fa[tu] = u;
tu = tt;
}
while(tv != v){
int tt = fa[tv];
fa[tv] = v;
tv = tt;
}
return true;
}
LL dp[N][];
LL t1[N], t2[N], t3[N];
void DFS(int o, int u){
for(int v : e1[u]){
if(v == o) continue;
DFS(u, v);
}
if(col[u]) {
dp[u][] = ;
dp[u][] = ;
for(int v : e1[u]){
if(v == o) continue;
dp[u][] = (dp[u][] * (dp[v][] + dp[v][])) % mod;
}
}
else {
dp[u][] = ;
dp[u][] = ;
int k = e1[u].size();
if(k){
for(int i = ; i < k; ++i){
if(e1[u][i] == o)
t1[i+] = ;
else {
t1[i+] = dp[e1[u][i]][] + dp[e1[u][i]][];
dp[u][] = dp[u][] * t1[i+] % mod;
}
}
t2[] = t3[k+] = ;
for(int i = ; i <= k; ++i)
t2[i] = t1[i] * t2[i-] % mod;
for(int i = k; i >= ; --i)
t3[i] = t1[i] * t3[i+] % mod;
for(int i = ; i < k; ++i){
int v = e1[u][i];
if(v == o) continue;
dp[u][] = (dp[u][] + dp[v][] * t2[i] % mod * t3[i+] % mod) % mod;
}
}
}
}
void Ac(){
for(int i = , v; i <= n; ++i){
scanf("%d", &v);
if(v) vc[v].pb(i);
col[i] = v;
}
for(int i = , u, v; i < n; ++i){
scanf("%d%d", &u, &v);
e1[u].pb(v);
e1[v].pb(u);
}
dfs(, );
for(int i = ; i <= n; ++i){
for(int j = ; j < vc[i].size(); ++j){
if(!Link(vc[i][],vc[i][j],i)) {
puts("");
return ;
}
}
}
DFS(, );
printf("%I64d\n", dp[][]);
}
int main(){
while(~scanf("%d%d", &n, &k)){
Ac();
}
return ;
}
CodeForces - 1118 F2 Tree Cutting的更多相关文章
- Codeforces 1118 F2. Tree Cutting (Hard Version) 优先队列+树形dp
题目要求将树分为k个部分,并且每种颜色恰好在同一个部分内,问有多少种方案. 第一步显然我们需要知道哪些点一定是要在一个部分内的,也就是说要求每一个最小的将所有颜色i的点连通的子树. 这一步我们可以将所 ...
- Codeforces Round #540 (Div. 3) F1. Tree Cutting (Easy Version) 【DFS】
任意门:http://codeforces.com/contest/1118/problem/F1 F1. Tree Cutting (Easy Version) time limit per tes ...
- 贪心 Codeforces Round #300 A Cutting Banner
题目传送门 /* 贪心水题:首先,最少的个数为n最大的一位数字mx,因为需要用1累加得到mx, 接下来mx次循环,若是0,输出0:若是1,输出1,s[j]--: 注意:之前的0的要忽略 */ #inc ...
- 水题 Codeforces Round #300 A Cutting Banner
题目传送门 /* 水题:一开始看错题意,以为是任意切割,DFS来做:结果只是在中间切出一段来 判断是否余下的是 "CODEFORCES" :) */ #include <cs ...
- 【HDU 5909】 Tree Cutting (树形依赖型DP+点分治)
Tree Cutting Problem Description Byteasar has a tree T with n vertices conveniently labeled with 1,2 ...
- BZOJ3391: [Usaco2004 Dec]Tree Cutting网络破坏
3391: [Usaco2004 Dec]Tree Cutting网络破坏 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 47 Solved: 37[ ...
- BZOJ 3391: [Usaco2004 Dec]Tree Cutting网络破坏( dfs )
因为是棵树 , 所以直接 dfs 就好了... ---------------------------------------------------------------------------- ...
- Tree Cutting
Tree Cutting Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/131072 K (Java/Others) Prob ...
- Problem - D - Codeforces Fix a Tree
Problem - D - Codeforces Fix a Tree 看完第一名的代码,顿然醒悟... 我可以把所有单独的点全部当成线,那么只有线和环. 如果全是线的话,直接线的条数-1,便是操作 ...
随机推荐
- Ubuntu 执行chmod -R 777 / 挽救方法
mgj怎么会有堪比rm -rf /*这样神奇的命令,本想着把当前目录下的权限改为777,没想到把整个/目录下全设成777了,直觉告诉我好像哪里有些不对劲,好在一顿xjb折腾最终弄好了,应该没啥大问题, ...
- 五、Python基础(2)
五,Python基础(2) 1.数据类型基础 (一)什么是数据类型? 用于区分变量值的不同类型. (二)为何对数据分类? 针对不同状态就应该用不同类型的数据去标识. (三)数据类型分类 1.数字类型 ...
- 新IT运维时代 | Docker运维之最佳实践-上篇
容器技术的发展可以分为两个阶段,第一个阶段聚焦在IaaS层,仅仅把容器当做更轻量级虚拟机来使用,解决了应用运行时进程级资源隔离的问题:随着Docker的出现,容器虚拟化才有了统一的平台,由此容器技术发 ...
- Docker——理解好镜像和容器的关系
关注公众号,大家可以在公众号后台回复“博客园”,免费获得作者 Java 知识体系/面试必看资料. 镜像也是 docker 的核心组件之一,镜像时容器运行的基础,容器是镜像运行后的形态.前面我们介绍了 ...
- 面向对象---prototype、__proto__、实例化对象三者之间的关系
1.构造函数 a.什么是构造函数? 解释:通过关键字new 创建的函数叫做构造函数 作用:用来创建一个对象 废话少说直接上代码,首先我们还是创建一个构造函数人类 然后我们在创建两个实例,一个凡尘 一个 ...
- 一文了解:Redis的RDB持久化
一文了解:Redis的RDB持久化 Redis是内存数据库,为了保证数据不在故障后丢失,Redis需要将数据持久化到硬盘上. Redis持久化有两种方式:一种是快照,全量备份.一种是AOF方式,连续增 ...
- 第五章-处理多窗口 | Electron实战
本章主要内容: 使用JavaScript Set数据结构跟踪多个窗口 促进主进程和多个渲染器进程之间的通信 使用Node APIs检查应用程序运行在那个平台上 现在,当Fire Sale启动时,它为U ...
- 使用Graphlab参加Kaggle比赛(2017-08-20 发布于知乎)
之前用学生证在graphlab上申了一年的graphlab使用权(华盛顿大学机器学习课程需要)然后今天突然想到完全可以用这个东东来参加kaggle. 下午参考了一篇教程,把notebook上面的写好了 ...
- Go调度器介绍和容易忽视的问题
本文记录了本人对Golang调度器的理解和跟踪调度器的方法,特别是一个容易忽略的goroutine执行顺序问题,看了很多篇Golang调度器的文章都没提到这个点,分享出来一起学习,欢迎交流指正. 什么 ...
- 用友网络科技Java高级开发面试题(2019)
面试时间:2019年8月18日上午9:30 面试岗位:Java高级开发 面试形式:电话面试 这些天在boss上逛了下,看见北京Java开发工资比较诱人,便萌生了去北京的想法,做一名北漂的程序猿.约了几 ...