1154 字
6 分钟
题解合集
1.25
2112E. Tree Colorings
题意
给定一棵树, 这棵树的合法染色方案定义如下:
- 某节点可以被涂成绿色, 蓝色, 黄色的其中一种
- 树根为绿色.
- 对于所有的蓝色和绿色节点, 它们之间两两可达, 不经过任何黄色节点.
- 对于所有的黄色和绿色节点, 它们之间两两可达, 不经过任何蓝色节点.
现在, 给你一棵树(树未知)的合法染色方案数恰好为m, 求这棵树的最少节点数(若不存在输出-1).
题目分析
请注意题意中的第3. “对于所有的蓝色和绿色节点, 它们之间两两可达, 不经过任何黄色节点”意思是:
- 蓝色节点和蓝色节点之间两两可达, 不经过任何黄色节点.
- 蓝色结点和绿色节点之间两两可达, 不经过任何黄色节点.
- 绿色节点和绿色节点之间两两可达, 不经过任何黄色节点.
同样地, 由第4条我们会得到: 绿色节点和绿色节点之间两两可达, 不经过任何蓝色节点. 所以说绿色和绿色之间只能有绿色节点. 这是这道题读题上的一个坑点(见样例3解释).
准备工作
我们首先考虑一个更简单的问题. 对于某个给定的树, 我们如何求出这棵树的合法染色方案数呢? 假设对应的染色方案数为, 则我们可以发现:
- 树根的染色方案数为1.
- 考察第一个孩子和它管辖的子树, 如果染蓝色, 则整个子树必须染成蓝色(因为绿色和绿色节点之间必须没有其他颜色). 如果染黄色, 则整个子树都必须染成黄色. 如果染绿色: 这个子树的染色方案数就是! 也就是说, 第一个子树的染色方案数为.
- 其他子树同理.
- 各个子树之间互不影响, 由乘法原理, 得到
正式开始
于是, 题目转化成了给定m, 求的所有树中节点数最小的树.
我们假定这个存在, 可以分两种情况考虑:
- 只有一棵子树, 此时, .(因为根节点被分出来了).
- 有多棵子树, 我们可以把其中一棵分出来. , 设, 则
我们会发现这个式子右边恰好相当于一棵有着子树的树的合法染色方案数. 所以说我们成功地把分解成了两个树的合法染色数的积. , 且.
如果很难理解的话, 看看下面这两张图.
第一种情况:

第二种情况:

题目要我们找到对应的节点数最小值, 我们可以递归地搜索对应的节点数最小值, 和对于的所有因数来说, 对应的节点数最小值加的节点数最小值. 然后取这两种结果中更小的那个即可.
加上记忆化搜索后, 状态空间的大小为, 对于每个需要分解因数, 用时大约为, 所以时间复杂度为. 本题时限为4s, 足以通过.
AC代码
使用记忆化搜索. 链接提交记录
/*--------head files---------*/// 此处省略大量模板定义, 见原链接.
/*---------variables---------*/struct DP { ll dp[M]; DP() { memset(dp, -1, sizeof(dp)); } ll solve(int m) { if (m == 1) { return 1; } else if (m == 2) { return 0; }
if (dp[m] != -1) { return dp[m]; }
ll ret = INFLL; // 1e18 ret = min(ret, solve(m - 2) + 1); for (int i = 2; i <= m / i; i++) { if (m % i != 0) { continue; } ret = min(ret, solve(i) + solve(m / i) - 1); } dp[m] = ret; return ret; }} dp;
/*---------functions---------*/
/*---------solutions---------*/void preprocess() {}void reset() {}void solution() { /*code here*/ ll m; cin >> m; if (m % 2 == 0) { cout << "-1\n"; return; } cout << dp.solve(m) << '\n';}/*-----------main------------*/int main() { int num_of_Task = 1; cin >> num_of_Task; preprocess(); for (int _t = 1; _t <= num_of_Task; _t++) { #ifndef ONLINE_JUDGE cout << "test case " << _t << " :\n"; cerr << "test case " << _t << " :\n"; #endif reset(); solution(); }}/*--------by ykindred--------*/