隐藏页面特效

【NOIP2022】建造军营

1|0题面


1|1题目描述


A 国与 B 国正在激烈交战中,A 国打算在自己的国土上建造一些军营。

A 国的国土由 n 座城市组成,m 条双向道路连接这些城市,使得任意两座城市均可通过道路直接或间接到达。A 国打算选择一座或多座城市(至少一座),并在这些城市上各建造一座军营。

众所周知,军营之间的联络是十分重要的。然而此时 A 国接到情报,B 国将会于不久后袭击 A 国的一条道路,但具体的袭击目标却无从得知。如果 B 国袭击成功,这条道路将被切断,可能会造成 A 国某两个军营无法互相到达,这是 A 国极力避免的。因此 A 国决定派兵看守若干条道路(可以是一条或多条,也可以一条也不看守),A 国有信心保证被派兵看守的道路能够抵御 B 国的袭击而不被切断。

A 国希望制定一个建造军营和看守道路的方案,使得 B 国袭击的无论是 A 国的哪条道路,都不会造成某两座军营无法互相到达。现在,请你帮 A 国计算一下可能的建造军营和看守道路的方案数共有多少。由于方案数可能会很多,你只需要输出其对 1,000,000,007(109+7) 取模的值即可。两个方案被认为是不同的,当且仅当存在至少一 座城市在一个方案中建造了军营而在另一个方案中没有,或者存在至少一条道路在一个 方案中被派兵看守而在另一个方案中没有。

1|2输入输出与样例


输入格式

第一行包含两个正整数 n,m,分别表示城市的个数和双向道路的数量。

接下来 m 行,每行包含两个正整数 ui,vi,描述一条连接 uivi 的双向道路。保证没有重边和自环。

输出格式

输出一行包含一个整数,表示建造军营和看守道路的方案数对 1,000,000,007(109+7) 取模的结果。

样例输入

2 1 1 2

样例输出

5

样例解释

A 国有两座城市,一条道路连接他们。所有可能的方案如下:

  • 在城市 1 建军营, 不看守这条道路;
  • 在城市 1 建军营, 看守这条道路;
  • 在城市 2 建军营, 不看守这条道路;
  • 在城市 2 建军营, 看守这条道路;
  • 在城市 1,2 建军营, 看守这条道路。

1|3数据规模与约定


对所有数据,保证 1n5×105n1m1061ui,vinuivi

各测试点的信息如下

测试点编号 n m 特殊条件
13 8 10
47 16 25
89 3000 5000
1011 5×105 106 特殊性质 A
1214 5×105 106 m=n1
1516 5×105 106 m=n
1720 5×105 106

特殊性质 A:保证 m=n1 且第 i 条道路连接城市 ii+1



2|0题解


2|1方法概述


双连通分量缩点,再 树上DP+容斥
建议先去熟悉一下tarjan算法以及相关概念(如割点、割边、缩点)。

2|2推荐阅读


一篇做题思路相当完整的题解

适合捋思路,它的DP稍微有点复杂,不过大差不差(?)

一篇没有用双缩点的神仙题解

就是不明觉厉……

一篇讲双连通分量的前置博客

不知道我啥时候才会自己写一篇

本篇题解内容均基于以上三篇(以及个人理解)。

2|3部分分


测试点编号 n m 特殊条件 解法
13 8 10 solve1
47 16 25 solve1
89 3000 5000 solve3_plus
1011 5×105 106 特殊性质 A solve2
1214 5×105 106 m=n1 solve3
1516 5×105 106 m=n solve3_plus
1720 5×105 106 正解

就算不会tarjan和缩点,骗个45pts也是没什么悬念的。

solve[1]:暴搜

枚举所有2n种军营的选法。
枚举后将得到一张“子图”,在这张“子图”中对边进行分类:哪些边是必须的,哪些边可选可不选,以此进行统计。

注意,这张“子图”实际和原图拥有完全一致的点边结构。不同的是,“子图”中的一些点被标记为军营

若可选可不选的边有x条,则对当前选法答案的贡献是×2x
(必须的边没有贡献,因为只有一种选法)

判断必须的边。
首先,可以对“子图”再进行一次简化。任意端点不是标记点的边一定是可选可不选的,因为它对“战局1”没有任何影响。(1:“战局”即 军营的连通性)
于是,在进行统计之后,可将战局外的边和点忽略,得到一张“真·子图”。

接下来考虑如何在“真·子图”中进行边的分类。

这时会发现一个性质。

注意,并非是此性质需要前文的推断作为基础。实际上,只有当我们产生“分类边”这一需求,才会“顺理成章”地得出这一性质)

必须的边都是“真·子图”中的割边,可选可不选的边都是“真·子图”中的非割边。
这一点根据割边的定义得出,不需要证明。

对“真·子图”进行一次tarjan,就可以完成分类以及统计。
(关于tarjan算法,此处不多赘述)

这里说这么多是因为这个性质会从头用到尾

考虑时间复杂度。
进行2n次枚举。每次枚举跑一遍tarjan,是O(n)的复杂度。
共是O(n2n)复杂度。n16,则n2n约为1e6
是挺正确的时间复杂度。

solve[2]:链上解

利用特殊性质。
数据保证图是一条链,实际上是将求边的难度降低了。
与solve[1]情况不同的是,可以简单的排除掉2n中的许多不合法情况。对于一条链,保证连通性的也只会是一条子链,或者说一个子区间。此时,只需要头尾两个端点就能确定边的情况。

求[l,r]对答案的贡献。
先抛开枚举不谈,假使已经确定了一个区间[l,r]。
此时可选可不选的边是[1,l]和[r,n]的边,必选的是[l,r]的边。
统计答案时,只需要边的数量,而不需要具体的边。
贡献应当是:

sum=2l+nr1

事实上,还忽略了一个东西。
即使在这个区间[l,r]中,所有边都必须选中,点却不一定。所以答案还要×2lr1。(只有l和r本身必选)
于是有:

sum=2l+nr1×2lr1=2n2

所以这个答案和l、r压根没关系嘛。

答案和时间复杂度。
l和r的可能配对统共有Cn2种。
于是乎,答案就是:

ans=Cn2×2n2

是一个类似于O(1)解决的时间复杂度。
是一个类似于O(n)解决的时间复杂度。

solve[3]:树上DP

其实已经极其接近正解了,不会有人只写树上DP却不写正解吧。(?
于是决定放在正解部分说明。

solve[3]_plus:树上DP_plus

测试点8~9
进行缩点的树上背包DP。
(而不是正解里更优的DP,不打算细嗦)
f(u,i)表示当前节点u、选了i个军营的情况数。

测试点15~16
比起solve[3]多的一条边会形成一个环。
对这个环进行特判可以解决。(虽然有点麻烦)
正解也可以解决。(不那么麻烦)

2|4正解做法


(只是其中一种做法,仅供参考)

想在前面

会发现“环”是一个挺关键的麻烦。
前面的性质也提到了“割边”,其实隐隐约约就能感觉到正解的方向了。
像这种计数题肯定是用DP解决无疑的,但是给出的图又不保证是树。
要DP肯定还得是树上DP,所以要尝试把图变成树。

这不就巧了吗,又是环,又是割边,又是图变成树……
于是就双连通分量缩点,利用所有条件解决所有问题,挺完美的。

P.S.其实我做题的时候是卡在这里的,如下

:话说为什么可以缩点啊,即使是双连通分量,难道对于其中的部分点时一定不会是必选吗?
:它是个环啊!是个环啊!环!
:(连滚带爬)

P.S.当我还在摸鱼写题解的时候,勤奋的同学已经怒切下一道了,恐怖如斯QAQ

缩点

其实直接缩就可以。
对于每个新点记一下包含了多少原来的点,包含了多少原来的边。
缩点时需要记哪些东西,一般都可以毛估估出来。
或者一开始就多记一点也无所谓,不影响,而且比较保险。

树上DP

缩点之后就只剩下割边了,也就是说,图变成了树。
于是就可以快乐的树上DP。(DP还是多练练,熟悉下解题思路)

状态定义:
f(u,1)表示点u的子树中至少选了一个军营,并且军营和u连通的情况数。
f(u,0)表示点u的子树中不选军营的情况数。

在考虑转移前先考虑答案统计。

注意,DP优先证明正确性,但是可以仅仅脑内自证,不详细写出。正因如此,这里仅仅是考虑答案统计,而不是答案统计

对于每个节点,只统计子树外无军营且不选u的树边情况下的答案。
联系到状态定义,就可以保证不重不漏。

这里额外补充一点定义:
sumV(u)表示缩点后节点u包含的点数
sumE(u)表示缩点后节点u包含的边数
sumS(u)表示缩点后节点u子树的边数
fa(u)表示缩点后节点u的父亲节点

状态转移:

f(u,0)=2sumE(u)×Πfa(v)=u2f(v,0)f(u,1)=fa(v)=uf(u,0)×f(v,1)+f(u,1)×(2f(v,0)+f(v,1))

代码实现中要注意f(u,1)转移的先后顺序。
应当先乘再加,或者提前存储f(u,1)的值。

初始化状态:

f(u,0)=2sumE(u),f(u,1)=2sumV(u)+sumE(u)2sumE(u)

答案统计:
设根节点为rt(root的简写),缩点后树的点集为V

ans=uVurtf(u,1)×2sumS(rt)sumS(u)1+f(rt,1)

根节点的话,一般是选1,不过其实选哪个都差不多。


__EOF__

本文作者Meteor2008
本文链接https://www.cnblogs.com/meteor2008/p/17645154.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   _kilo-meteor  阅读(316)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示