给一张图,其中一些点称为关键点。
斯坦纳树的定义就是能覆盖关键点的连通子图,为什么叫连通子图,可以发现答案子图可以为一棵树,否则如果有环,可以删去环上任意一条边,新图也联通。
\(\textup{最小斯坦纳树}\)
\(Link\)
题意:给定一张带权无向图,其中有一些点是关键点,求连通子图的最小长度。
可以发现答案子图一定为一棵树,否则如果有环,可以删去环上任意一条边,新图也联通。
这是个 NP-hard 问题,可能没办法在多项式时间复杂度内(\(\mathcal{O}(\mathcal{n}^k)\) 或 \(\mathcal{O}(\mathcal{nk})\))解决,考虑状压。
子图的状态肯定无法压进 dp,考虑将关键点的状态压进 dp。
由于答案是一棵树,可以设 \(f_{i,S}\) 表示以 \(i\) 为根,且关键点覆盖状态为 \(S\) 的最小长度。
我们可以将以 \(i\) 为根的树分成两类:\(i\) 的度数为 \(1\),\(i\) 的度数大于 \(1\)。
分讨:
- \(i\) 的度数为 \(1\),则这个点的转移来自于他唯一的连边,我们就考虑通过 \(i\)的相邻点来转移,设这个点为 \(j\),则
- \(i\) 的度数大于 \(1\),则可以将这个图分成 \(i\) 的若干个子树,就可以通过枚举子集转移:
实现方面,对于第一种转移,可以想到最短路算法的松弛操作,将整张图松弛,先将整张图更新的点扔进队列,然后用第一种转移的转移式更新整张图的 \(f\),通过最短路算法实现。
可以发现图是比较稀疏的,可以复活死去的 \(SPFA\), 这个转移的时间复杂度卡满的话是 \(\mathcal{O}(2^knm)\),和枚举子集比起来你会惊奇发现这和枚举子集的时间复杂度差不多。
对于第二种转移,直接枚举子集,复杂度 \(\mathcal{O}(3^kn)\)
讲一下枚举子集的时间复杂度,之前一直不是很懂。
设集合大小为 \(T\),则大小为 \(0\) 的子集个数为 \(C_n^0\),大小为 \(1\) 的子集个数为 \(C_n^1\)...大小为 \(n\) 的子集个数为 \(C_n^n\)。
枚举的总复杂度就是 \(2^0 \times C_n^0 + 2^1 + C_n^1 + ... 2^n + c_n^n = \sum_{k = 0}^{n} 2^k C_n^k = \sum_{k = 0}^{n} 2^k 1^{n-k}C_n^k = (2 + 1)^n = 3^n\)。
最后 \(ans = \min \{f_{i,2^{k} - 1}\}\)。
游览计划
可以发现这题很板,只是加了一个点权转边权和输出方案。
输出方案在每次转移时加一个 \(pre\) 数组,然后 dfs。
点权转边权可以考虑将第二个转移改成
因为两边我们都算了一次 \(i\) 节点,减了就行。