当前位置: 首页 > news >正文

ch09 题目参考思路

ch09 - 拓扑排序与基环树

SAT 问题

  • 知识点:基环森林
  • 思路:
    • 题意解释:题目会输入 n 对二元关系,每对二元关系要保证对应位置填数不同(只能填 0 或 1)。如样例 1 输入 2,3,4,1,对应四对二元关系,分别是 (1, 2),(2, 3),(3, 4),(4, 1),其中 (1,2) 表示 1,2 位置所填的数不能相同(比如 1 填 T,那么 2 只能填 F,或者 1 填 F,那 2 只能填 T),其他二元关系也是如此。
    • 对于每一对二元关系,我们可以理解为一条无向边,比如二元关系 (1, 2),可以认为节点 1 和节点 2 之间连了一条边,以此类推,我们能得到下图所示的基环树(左 1)。
      SAT问题
    • 建图之后,问题可以变成在图上染色的过程,当某个点确定之后,相邻节点的颜色也确定了,依次类推,整张图的染色也确定了,由于初始节点有两种染色方案,因此总的方案数为 2。
      • 情形 1:图上环的长度为奇数(有奇数个节点),那么不存在可行的染色方案。
      • 情形 2:图上的一个连通块中不止有环,还有连接其他节点,这些节点不会影响染色过程,可以忽略。
      • 综上所述,如果图中不存在奇数长度的环,且忽略所有不在环上的节点后,图上只存在若干长度为偶数的环,记环的个数为 k k k,并且每个长度为偶数的环的染色方案为 2,根据乘法原理,总的方案数为 2 k 2^k 2k(可以通过样例 2 建图理解)。
    • 代码思路:先根据拓扑排序的思路,将所有不在环上的节点排除,再统计每个环上节点的个数,并统计环的个数 k k k。如果存在奇数长度的环,答案为 0,否则答案为 2 k 2^k 2k

收敛的数组

  • 知识点:基环树、并查集
  • 思路:
    • 对于每一轮赋值操作, i = a i i = a_i i=ai,可以认为数 i i i 变成了 a i a_i ai,因此可以看成是节点 i i i 到节点 a i a_i ai 有一条出边,表示从节点 i i i 能一步到达节点 a i a_i ai。更具体地,每个数 i i i 都看成一个节点,编号从 1 ∼ n 1 \sim n 1n,对于输入的每个 a i a_i ai,可以认为从节点 i i i 到节点 a i a_i ai 有一条出边,形成一个基环内向森林(可能有多个基环内向树)。
    • 题目的问题在图上可以转换为,修改最少的边使得可以找到一个节点 x,所有节点(包括 x 本身)能经过 n - 1 条边到达 x。
    • 对于一棵基环内向树而言
      • 选择的节点 x 必须在环上,因为如果选择的点 x 在环外,那么环上的点无论如何都无法到达 x,不符合要求。
      • 环上的节点只能有一个(自环),因为如果环上的节点大于等于 2,随意选择任何一个节点作为 x,那么每个节点到达 x 的距离都是不一样的,因此不存在任何距离 k(题目中是 n - 1),使得每个节点到 x 的距离都是 k。
      • 综上所述,对于每一棵基环内向树而言,我们需要找到一个终点,让它变成自环,这样才能使得每个点到终点的距离为 n - 1。
    • 统计需要修改的边数
      • 记该基环内向森林中有 cnt 棵基环内向树。
      • 如果一棵基环内向树中本身就有一个自环,那么可以把它作为终点 x,所有其他树需要连一条边到这个终点上(或者该树的其他点上,效果都一样),需要的边数取决于有多少棵其他的基环内向树,即 cnt - 1
        • 可以通过并查集统计基环内向树的数量(同一棵树上的节点可以认为在同一个集合中,最后统计有多少个集合)
      • 如果不存在任何一棵基环内向树中有自环,则需要额外修改一条边,将某个节点改成自环。总共需要修改 cnt 条边。

Piggy banks

  • 知识点:基环树、并查集
  • 思路:
    • 题意解释:有 n 个存钱罐和 n 把钥匙,要想获得第 i 个存钱罐中的钱,有两种方式,一种是将存钱罐打碎,另一种是通过它对应的第 i 把钥匙开启。
      • 每个存钱罐中除了有钱之外,可能还放有其他存钱罐的钥匙。问最少需要打碎多少存钱罐,将里面的所有钱全部拿出来。
    • 将每个罐子看成一个节点,如果编号为 x 的罐子中有着编号为 i 罐子的钥匙,那么可以认为,有一条从节点 x 到节点 i 的有向边,表示通过节点 x 能打开 i 号罐子,从而形成基环外向森林。例如,对于样例而言,如下图所示,其中圆形表示罐子,三角形表示罐子钥匙。
      P3420 [POI2005]SKA-Piggy Banks
    • 对于一棵基环外向树而言,只需要打碎其中一个在环上的罐子,就能访问到所有其他罐子了。因此问题就变成计算有多少棵基环外向树的问题了(每一棵基环外向树都需要打碎一个罐子)
      • 同样地,可以通过并查集统计有多少棵基环外向树(每一个基环外向树是一个集合)
http://www.xdnf.cn/news/363763.html

相关文章:

  • 不黑文化艺术学社首席艺术家孙溟㠭浅析“雪渔派”
  • AI赋能智能客服革新:R²AIN SUITE 如何破解医疗行业服务难题?
  • 哈希表扩容怎么处理新插入的值?Swift 是怎么做的?
  • 力扣-19.删除链表的倒数第N个结点
  • Nacos源码—Nacos配置中心实现分析
  • Mysql数据库进阶
  • LMMSE、MMSE和LS
  • vscode 配置doxygen注释和snippet
  • RT-Thread 深入系列 Part 1:RT-Thread 全景总览
  • 【赛元8523触摸按键开发调试】
  • 【vue3】vue3中封装懒加载指令
  • C++ Lambda表达式详解:匿名函数的艺术与现代编程实践
  • 数字经济时代下的消费行为变迁与经济学启示
  • 解决 Redis 缓存与数据库一致性问题的技术指南
  • 【Linux网络】Socket-TCP相关函数
  • 大模型提示词策略
  • 赋能智能交通:时空图卷积网络引领速度预测新变革
  • PostgreSQL技术大讲堂 - 第89讲:重讲数据库完全恢复
  • 图解gpt之Seq2Seq架构与序列到序列模型
  • 【某OTA网站】phantom-token 1004
  • vue 监听元素大小变化 element-resize-detector
  • 《Vuejs与实现》第 6 章(原始值响应式方案)
  • 蓝桥杯青少 图形化编程(Scratch)编程题每日一练——图形特效
  • 嵌套路由~
  • leetcode - 双指针问题
  • Linux C语言线程编程入门笔记
  • uni-app 中的条件编译与跨端兼容
  • 区块链详解
  • 独立自主的网络浏览器——Ladybird
  • 类加载器, JVM类加载机制