题解|2023暑期杭电多校01
1002.City Upgrading
树形DP、支配集
题意
crazyzhk居住在一个树形城市。有一天,这个城市的网络需要升级。为了实现这一目标,需要部署路由器。
每个路由器可以覆盖其所在的节点及其相邻节点,在节点 $i$ 上放置一个路由器的成本是 $a_i$
确保每个节点都得到覆盖的情况下,成本最低是多少
前置知识点
- 树形DP
- 支配集:给定无向图 $G=(V,E)$ ,称 $V$ 的一个子集 $S$ 为支配集,当且仅当对于 $V-S$ 中任何一个点 $v$ ,都有 $S$ 中的某个点 $u$ ,使得 $(u,v) \in E$
解题思路
要实现信号全覆盖,所选取的点集必须是一个支配集
题目求的是所有支配集中最小的cost,考虑树形DP
构造DP数组dp[N][3]
:
dp[i][0]
表示点 $i$ 属于支配集合,并且以点 $i$ 为根的子树都被覆盖了的情况下,支配集中所包含最少costdp[i][1]
表示点 $i$ 不属于支配集合,且以 $i$ 为根的子树都被覆盖,且 $i$ 被其不少于一个子节点覆盖的情况下,支配集所包含最少costdp[i][2]
表示点 $i$ 不属于支配集合,且以 $i$ 为根的子树都被覆盖,且 $i$ 没被子节点覆盖(将被父节点覆盖)的情况下,支配集中所包含最少cost
结合最小支配集的贪心思想,按DFS序的逆序进行DP,节点 $i$ 的子节点记为 $u$
对于第一种状态,dp[i][0]
含义为点 $i$ 属于支配集合,那么依次取每个儿子节点三种状态中的最小值,再把取得的最小值全部加起来再加1,就是dp[i][0]
的值了。即只要每个以 $i$ 的儿子为根的子树都被覆盖,再加上当前点 $i$ ,所需要的最少cost,DP转移方程如下:
$$
dp[i][0] = 1 + ∑min(dp[u][0], dp[u][1], dp[u][2])
$$
对于第三种状态,dp[i][2]
含义为点 $i$ 不属于支配集合,且 $i$ 被其父节点覆盖。那么说明点 $i$ 和点 $i$ 的儿子节点都不属于支配集合,所以点 $i$ 的第三种状态之和其儿子节点的第二种状态有关,方程为:
$$
dp[i][2] =∑dp[u][1]
$$
对于第二种状态,略有些复杂。
首先如果点 $i$ 没有子节点那么dp[i][1]
应该初始化为INF;否则为了保证它的每个以 $i$ 的儿子为根的子树被覆盖,那么要取每个儿子节点的前两种状态的最小值之和,因为此时点 $i$ 不属于支配集,不能支配其子节点,所以子节点必须已经被支配,与子节点的第三种状态无关。
如果当前所选状态中每个儿子都没被选择进入支配集,即在每个儿子的前两种状态中,第一种状态都不是所需点最小的,那么为了满足第二种状态的定义(因为点 $i$ 的第二种状态必须被其子节点覆盖,即其子节点必须有一个属于支配集,如果此时没有,就必须强制使一个子节点的状态为状态一),需要重新选择点 $i$ 的一个儿子节点为第一种状态,这时取花费最少的一个点,即取min(dp[u][0] - dp[u][1])
的儿子节点 $u$ ,强制取其第一种状态,其他的儿子节点取第二种状态,DP转移方程为:
$$dp[i][1] = \begin{cases}
INF ,i没有子节点 \newline
∑min(dp[u][0], dp[u][1]) + inc ,Otherwise \newline
\end{cases} \newline
$$
$$
其中,inc = \begin{cases}
0 ,上式的Otherwise中至少选择了一次状态一的子节点 \newline
min(dp[u][0] - dp[u][1]) ,Otherwise
\end{cases} \newline
$$
结果为根节点三个状态中的最小值
时间复杂度
$O(nlogn)$
参考程序
1 |
|
1005.Cyclically Isomorphic
字符串匹配
题意
对于两个字符串 $s_1$ , $s_2$ ,如果存在一个整数 $k$ 使得 $s_1$ 循环右移k位与 $s_2$ 相同,则称他们是"cyclically right-shifted"。
每组数据给出 $n$ 个长度为 $m$ 的字符串, $Q$ 次询问两个字符串是否"cyclically right-shifted"。
解题思路
对于每一字符串,找到其字典序最小的状态储存,每次询问时直接比较即可。
主要是时间复杂度难以证明
时间复杂度
找最小态储存 $n \times m^2$ ,比较 $Q \times m$
$Q \le \dfrac{1}{2} n(n-1) \Rightarrow$ 比较 $m \times n^2$
总复杂度: $O(mn \times (m+n))$ ,
$mn \le 10^5$ 下数据不变态的话就能卡过去
参考程序
1 | int solve() |
1009.Assertion
签到题
题意
多组数据
给定m件物品,分成n组
问:是否无论怎么分都至少有一组个数超过d
解题思路
平均分组,找最大那个组的个数和d比较
参考程序
1 | int solve() |