博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CodeForces - 1118 F2 Tree Cutting
阅读量:6217 次
发布时间:2019-06-21

本文共 3620 字,大约阅读时间需要 12 分钟。

题解:

  先注意到一定存在k种颜色,切成k个块, 然后要求每个块内的颜色都一样,所以可以发现同一种颜色一定在同一个块内,故任意2个相同颜色的最短路劲上的点的颜色都是该颜色。

  我们可以先把任意相同颜色点对的路径上的点的颜色都染成这个颜色。 如果发现存在一个点是已经有颜色的话,那么答案一定为0。

  至于怎么颜色, 我们可以暴力往上跑,然后压缩路径,和并查集一样的道理,路过的点都染色且压缩。

 

  这样就完成了第一部分的处理,接下来就是树DP了。

  定义dp[ u ][ 0 ] 的含义是 以u为根的子树,且u还未被划入任意一种颜色的方案数。

    dp[ u ][ 1 ] 的含义是 以u为根的子树,且u已被划入任意一种颜色的方案数。

 

  那么对于有颜色的点来说,

    dp[u][0] = 0;

              

      对于没有颜色的点来说:

       

    

代码:

/*code by: zstu wxktime: 2019/03/02Tags: 树DPProblem Link: http://codeforces.com/contest/1118/problem/F2Solve: https://www.cnblogs.com/MingSD/p/10462228.html*/#include
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
pll;const int inf = 0x3f3f3f3f;const int _inf = 0xc0c0c0c0;const LL INF = 0x3f3f3f3f3f3f3f3f;const LL _INF = 0xc0c0c0c0c0c0c0c0;const LL mod = 998244353;const int N = 3e5 + 100;int n, k, deep[N], fa[N], col[N];vector
vc[N], e1[N];void dfs(int o, int u){ deep[u] = deep[o] + 1; 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][2];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][0] = 0; dp[u][1] = 1; for(int v : e1[u]){ if(v == o) continue; dp[u][1] = (dp[u][1] * (dp[v][0] + dp[v][1])) % mod; } } else { dp[u][0] = 1; dp[u][1] = 0; int k = e1[u].size(); if(k){ for(int i = 0; i < k; ++i){ if(e1[u][i] == o) t1[i+1] = 1; else { t1[i+1] = dp[e1[u][i]][0] + dp[e1[u][i]][1]; dp[u][0] = dp[u][0] * t1[i+1] % mod; } } t2[0] = t3[k+1] = 1; for(int i = 1; i <= k; ++i) t2[i] = t1[i] * t2[i-1] % mod; for(int i = k; i >= 0; --i) t3[i] = t1[i] * t3[i+1] % mod; for(int i = 0; i < k; ++i){ int v = e1[u][i]; if(v == o) continue; dp[u][1] = (dp[u][1] + dp[v][1] * t2[i] % mod * t3[i+2] % mod) % mod; } } }}void Ac(){ for(int i = 1, v; i <= n; ++i){ scanf("%d", &v); if(v) vc[v].pb(i); col[i] = v; } for(int i = 1, u, v; i < n; ++i){ scanf("%d%d", &u, &v); e1[u].pb(v); e1[v].pb(u); } dfs(0, 1); for(int i = 1; i <= n; ++i){ for(int j = 1; j < vc[i].size(); ++j){ if(!Link(vc[i][0],vc[i][j],i)) { puts("0"); return ; } } } DFS(0, 1); printf("%I64d\n", dp[1][1]);}int main(){ while(~scanf("%d%d", &n, &k)){ Ac(); } return 0;}
View Code

 

 

 

    

转载于:https://www.cnblogs.com/MingSD/p/10462228.html

你可能感兴趣的文章
线性布局
查看>>
金蝶KIS,存货核算出库核算报错
查看>>
windows phone 2048 源代码奉上
查看>>
Ruby IDE
查看>>
用python实现简单的调度场算法
查看>>
rand(5) -> rand(7)
查看>>
SEO优化
查看>>
oracle10~11g在centos5~6版本上安装整体总结如下
查看>>
opencv配置(转)
查看>>
Spring Junit测试(非web,即不包含Controller测试)
查看>>
译文——The habits of highly successful people
查看>>
常见CSS与HTML使用误区
查看>>
模板类与类模板、函数模板与模板函数等的区别
查看>>
使用XPath查询带有命名空间(有xmlns)的XML(转)
查看>>
FastCgi与PHP-fpm之间是个什么样的关系
查看>>
对Navicat for MySQL 中1045错误的解决办法
查看>>
log日志
查看>>
使用CSS渐变
查看>>
ASP.NET ViewState详解
查看>>
阿里 Maven仓库
查看>>