热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

树形动态规划解决树切割问题(CodeForces1118F2)

题目概述:给定一棵带颜色节点的树,目标是找到一种方法,通过删除某些边使得每个连通分量内的节点颜色相同。需要计算出所有可能的合法边集的数量。使用动态规划的方法,特别是树形DP来解决问题。

题目要求:给定一棵树,每个节点都有一个颜色,目标是通过删除某些边,使每个连通分量内的节点颜色相同。任务是计算所有可能的合法边集的数量。


定义 $f[x][0/1]$ 表示在子树 $x$ 中,是否还存在与节点 $x$ 颜色相同的连通部分。其中 $f[x][1]$ 表示存在这样的连通部分,而 $f[x][0]$ 则表示不存在。


对于每种颜色,一旦确定了一个连通块,这个连通块内部就不能再被分割,因此状态转移方程如下:


$$f[x][1] = \prod (f[y][0] + f[y][1]), \quad f[x][0] = 0$$


如果可以分割的部分仅限于不同颜色连通块之间的无色节点,则状态转移方程为:


$$f[x][0] = \prod (f[y][0] + f[y][1]), \quad f[x][1] = \sum\limits_y (f[y][1]\prod\limits_{z \neq y}(f[z][0] + f[z][1]))$$



#include
#include
#include
#include
#include
#include
#include
#include
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair pii;
const int P = 998244353, INF = 0x3f3f3f3f;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}

#ifdef ONLINE_JUDGE
const int N = 1e6+10;
#else
const int N = 111;
#endif

int n, k;
vector g[N], q;
int col[N], c[N], cnt[N];
int f[N][2], prod[N];

void dfs(int x, int fa) {
cnt[x] = col[x]>0;
for (int y : g[x]) if (y != fa) {
dfs(y, x);
if (!col[x]) col[x] = col[y];
else if (col[y] && col[x] != col[y]) {
puts("0"), exit(0);
}
cnt[x] += cnt[y];
}
q.clear();
for (int y : g[x]) if (y != fa) q.pb(y);
prod[0] = 1;
int sz = q.size();
REP(i, 0, sz-1) {
int y = q[i];
prod[i+1] = (ll)prod[i] * (f[y][0] + f[y][1]) % P;
}
if (col[x]) f[x][1] = prod[sz];
else {
f[x][0] = prod[sz];
int tmp = 1;
PER(i, 0, sz-1) {
int y = q[i];
f[x][1] = (f[x][1] + (ll)tmp * f[y][1] % P * prod[i] % P) % P;
tmp = (ll)tmp * (f[y][0] + f[y][1]) % P;
}
}
if (c[col[x]] == cnt[x]) cnt[x] = col[x] = 0;
}

int main() {
scanf("%d%d", &n, &k);
REP(i, 1, n) scanf("%d", col + i);
REP(i, 1, n) ++c[col[i]];
REP(i, 2, n) {
int u, v;
scanf("%d%d", &u, &v);
g[u].pb(v), g[v].pb(u);
}
dfs(1, 0);
printf("%d\n", f[1][1]);
}

推荐阅读
  • 题目描述了一个病毒检测问题,要求使用AC自动机算法统计目标文本中多个模式串的出现次数。 ... [详细]
  • 深入理解BIO与NIO的区别及其应用
    本文详细探讨了BIO(阻塞I/O)和NIO(非阻塞I/O)之间的主要差异,包括它们的工作原理、性能特点以及应用场景,旨在帮助开发者更好地理解和选择适合的I/O模型。 ... [详细]
  • 本文介绍如何利用线段树高效地解决Luogu1471中的方差计算问题,包括区间修改和查询操作。 ... [详细]
  • 本文旨在介绍在iOS平台进行直播技术开发前的准备工作,重点讲解AVFoundation框架的基本概念和使用方法。通过对AVFoundation的深入理解,开发者能够更好地掌握直播应用中的音视频处理技巧。 ... [详细]
  • 本文详细介绍如何在 macOS 上编译 FFmpeg 3.1.1,并将其集成到 iOS 项目中,包括必要的环境配置和代码示例。 ... [详细]
  • 面临考试压力,急需解决四个编程问题,包括实现乒乓球的动态效果、计算特定日期是一年的第几天、逆序输出数字以及创建弹出菜单。每个问题的解决都能在TC3.0环境中获得50分。 ... [详细]
  • 本教程将深入探讨C#编程语言中的条件控制结构,包括if语句和switch语句的使用方法。通过本课的学习,您将掌握如何利用这些控制结构来实现程序的条件分支逻辑。 ... [详细]
  • 在尝试通过HTTP请求访问位于http://www.xxx.cn/net/Clicked.asmx的Web服务时,发现输入特定参数后,偶尔会接收到不成功的响应,表现为XML格式的空字符串。此现象并非每次发生,其根本原因尚不明确。 ... [详细]
  • 在Android应用开发过程中,经常需要在SQLite数据库中快速插入大量数据。本文通过实例探讨了不同插入方法的效率,并提供了优化建议。 ... [详细]
  • 本文介绍了Kettle资源库的基本概念、类型及其管理方法,同时探讨了Kettle的不同运行方式,包括图形界面、命令行以及API调用,并详细说明了日志记录的相关配置。 ... [详细]
  • 本文通过C++代码示例,详细介绍了如何利用邻接矩阵构建无向图,并实现图的深度优先遍历(DFS)。文章包括了完整的代码实现,以及对关键函数的解释。 ... [详细]
  • 本文探讨了如何在无向图中寻找一条从指定起点出发,确保不会连续两次访问同一条边的情况下,获得最大成本路径的方法。 ... [详细]
  • 题目链接:请点击这里。本题将图形视为波动,其中波峰被淹没时部分数减少,而波谷被淹没时部分数增加。因此,需要预先处理所有波峰和波谷的位置。特别地,图形的两端点需要特殊处理,可以通过设置边界条件来简化问题。 ... [详细]
  • 本题来自 BZOJ2004,链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2004。题目要求计算特定条件下的方案数,采用动态规划(DP)解决。由于任意两站间的距离不超过 p,因此每 p 个站点中所有的公交车都必须至少停靠一次。 ... [详细]
  • 本文概述了算法的基础概念,包括时间复杂度的计算规则,以及常见的递归算法的时间复杂度分析。同时,详细介绍了数组和链表的基本特性及其操作的时间复杂度,并提供了几个关于链表操作的具体示例。最后,探讨了栈和队列的概念及其应用,包括如何利用这些数据结构解决实际问题。 ... [详细]
author-avatar
holy190
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有