【NOIP2022】建造军营
1|0题面
1|1题目描述
A 国与 B 国正在激烈交战中,A 国打算在自己的国土上建造一些军营。
A 国的国土由 座城市组成, 条双向道路连接这些城市,使得任意两座城市均可通过道路直接或间接到达。A 国打算选择一座或多座城市(至少一座),并在这些城市上各建造一座军营。
众所周知,军营之间的联络是十分重要的。然而此时 A 国接到情报,B 国将会于不久后袭击 A 国的一条道路,但具体的袭击目标却无从得知。如果 B 国袭击成功,这条道路将被切断,可能会造成 A 国某两个军营无法互相到达,这是 A 国极力避免的。因此 A 国决定派兵看守若干条道路(可以是一条或多条,也可以一条也不看守),A 国有信心保证被派兵看守的道路能够抵御 B 国的袭击而不被切断。
A 国希望制定一个建造军营和看守道路的方案,使得 B 国袭击的无论是 A 国的哪条道路,都不会造成某两座军营无法互相到达。现在,请你帮 A 国计算一下可能的建造军营和看守道路的方案数共有多少。由于方案数可能会很多,你只需要输出其对 取模的值即可。两个方案被认为是不同的,当且仅当存在至少一 座城市在一个方案中建造了军营而在另一个方案中没有,或者存在至少一条道路在一个 方案中被派兵看守而在另一个方案中没有。
1|2输入输出与样例
输入格式
第一行包含两个正整数 ,分别表示城市的个数和双向道路的数量。
接下来 行,每行包含两个正整数 ,描述一条连接 和 的双向道路。保证没有重边和自环。
输出格式
输出一行包含一个整数,表示建造军营和看守道路的方案数对 取模的结果。
样例输入
样例输出
样例解释
A 国有两座城市,一条道路连接他们。所有可能的方案如下:
- 在城市 建军营, 不看守这条道路;
- 在城市 建军营, 看守这条道路;
- 在城市 建军营, 不看守这条道路;
- 在城市 建军营, 看守这条道路;
- 在城市 建军营, 看守这条道路。
1|3数据规模与约定
对所有数据,保证 ,,,。
各测试点的信息如下
测试点编号 | 特殊条件 | ||
---|---|---|---|
无 | |||
无 | |||
无 | |||
特殊性质 | |||
无 |
特殊性质 :保证 且第 条道路连接城市 与 。
2|0题解
2|1方法概述
先 双连通分量缩点,再 树上DP+容斥
建议先去熟悉一下tarjan算法以及相关概念(如割点、割边、缩点)。
2|2推荐阅读
适合捋思路,它的DP稍微有点复杂,不过大差不差(?)
就是不明觉厉……
不知道我啥时候才会自己写一篇
本篇题解内容均基于以上三篇(以及个人理解)。
2|3部分分
测试点编号 | 特殊条件 | 解法 | ||
---|---|---|---|---|
无 | solve1 | |||
无 | solve1 | |||
无 | solve3_plus | |||
特殊性质 | solve2 | |||
solve3 | ||||
solve3_plus | ||||
无 | 正解 |
就算不会tarjan和缩点,骗个45pts也是没什么悬念的。
solve[1]:暴搜
枚举所有种军营的选法。
枚举后将得到一张“子图”,在这张“子图”中对边进行分类:哪些边是必须的,哪些边可选可不选,以此进行统计。
注意,这张“子图”实际和原图拥有完全一致的点边结构。不同的是,“子图”中的一些点被标记为军营
若可选可不选的边有条,则对当前选法答案的贡献是。
(必须的边没有贡献,因为只有一种选法)
判断必须的边。
首先,可以对“子图”再进行一次简化。任意端点不是标记点的边一定是可选可不选的,因为它对“战局”没有任何影响。(1:“战局”即 军营的连通性)
于是,在进行统计之后,可将战局外的边和点忽略,得到一张“真·子图”。
接下来考虑如何在“真·子图”中进行边的分类。
这时会发现一个性质。
注意,并非是此性质需要前文的推断作为基础。实际上,只有当我们产生“分类边”这一需求,才会“顺理成章”地得出这一性质)
必须的边都是“真·子图”中的割边,可选可不选的边都是“真·子图”中的非割边。
这一点根据割边的定义得出,不需要证明。
对“真·子图”进行一次tarjan,就可以完成分类以及统计。
(关于tarjan算法,此处不多赘述)
这里说这么多是因为这个性质会从头用到尾
考虑时间复杂度。
进行次枚举。每次枚举跑一遍tarjan,是的复杂度。
共是复杂度。,则约为。
是挺正确的时间复杂度。
solve[2]:链上解
利用特殊性质。
数据保证图是一条链,实际上是将求边的难度降低了。
与solve[1]情况不同的是,可以简单的排除掉中的许多不合法情况。对于一条链,保证连通性的也只会是一条子链,或者说一个子区间。此时,只需要头尾两个端点就能确定边的情况。
求[l,r]对答案的贡献。
先抛开枚举不谈,假使已经确定了一个区间[l,r]。
此时可选可不选的边是[1,l]和[r,n]的边,必选的是[l,r]的边。
统计答案时,只需要边的数量,而不需要具体的边。
贡献应当是:
事实上,还忽略了一个东西。
即使在这个区间[l,r]中,所有边都必须选中,点却不一定。所以答案还要。(只有l和r本身必选)
于是有:
所以这个答案和l、r压根没关系嘛。
答案和时间复杂度。
l和r的可能配对统共有种。
于是乎,答案就是:
是一个类似于O(1)解决的时间复杂度。
是一个类似于O(n)解决的时间复杂度。
solve[3]:树上DP
其实已经极其接近正解了,不会有人只写树上DP却不写正解吧。(?
于是决定放在正解部分说明。
solve[3]_plus:树上DP_plus
测试点8~9
进行缩点的树上背包DP。
(而不是正解里更优的DP,不打算细嗦)
表示当前节点、选了个军营的情况数。
测试点15~16
比起solve[3]多的一条边会形成一个环。
对这个环进行特判可以解决。(虽然有点麻烦)
正解也可以解决。(不那么麻烦)
2|4正解做法
(只是其中一种做法,仅供参考)
想在前面
会发现“环”是一个挺关键的麻烦。
前面的性质也提到了“割边”,其实隐隐约约就能感觉到正解的方向了。
像这种计数题肯定是用DP解决无疑的,但是给出的图又不保证是树。
要DP肯定还得是树上DP,所以要尝试把图变成树。
这不就巧了吗,又是环,又是割边,又是图变成树……
于是就双连通分量缩点,利用所有条件解决所有问题,挺完美的。
P.S.其实我做题的时候是卡在这里的,如下
:话说为什么可以缩点啊,即使是双连通分量,难道对于其中的部分点时一定不会是必选吗?
:它是个环啊!是个环啊!环!
:(连滚带爬)
P.S.当我还在
摸鱼写题解的时候,勤奋的同学已经怒切下一道了,恐怖如斯QAQ
缩点
其实直接缩就可以。
对于每个新点记一下包含了多少原来的点,包含了多少原来的边。
缩点时需要记哪些东西,一般都可以毛估估出来。
或者一开始就多记一点也无所谓,不影响,而且比较保险。
树上DP
缩点之后就只剩下割边了,也就是说,图变成了树。
于是就可以快乐的树上DP。(DP还是多练练,熟悉下解题思路)
状态定义:
表示点的子树中至少选了一个军营,并且军营和连通的情况数。
表示点的子树中不选军营的情况数。
在考虑转移前先考虑答案统计。
注意,DP优先证明正确性,但是可以仅仅脑内自证,不详细写出。正因如此,这里仅仅是考虑答案统计,而不是答案统计
对于每个节点,只统计子树外无军营且不选u的树边情况下的答案。
联系到状态定义,就可以保证不重不漏。
这里额外补充一点定义:
表示缩点后节点包含的点数
表示缩点后节点包含的边数
表示缩点后节点子树的边数
表示缩点后节点的父亲节点
状态转移:
代码实现中要注意转移的先后顺序。
应当先乘再加,或者提前存储的值。
初始化状态:
答案统计:
设根节点为(root的简写),缩点后树的点集为
根节点的话,一般是选,不过其实选哪个都差不多。
__EOF__

本文链接:https://www.cnblogs.com/meteor2008/p/17645154.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文来自博客园,作者:_kilo-meteor,转载请注明原文链接:https://www.cnblogs.com/meteor2008/p/17645154.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!