Section 7.5

master
大蒟蒻 9 years ago
parent 5f916ae0c8
commit 19fe3a01d5

@ -529,10 +529,27 @@ Manacher 模板题
\subparagraph{使用网络流算法} 实际上,可以将二分图最大匹配问题看成是最大流问题的一种特殊情况。首先:建立源点$s$和汇点$t$,从$s$$X$集合的所有顶点引一条边,容量为$1$,从$Y$集合的所有顶点向$t$引一条边,容量为$1$。然后将二分图的所有边看成是从$X_i$$Y_j$的一条有向边,容量为$1$。求最大匹配就是求$s$$t$的最大流。
\subparagraph{使用匈牙利算法:}
利用所有边的容量都是$1$以及二分图的性质,我们还可以将二分图最大匹配算法更简单地实现:\\
假设$M$是二分图$G$的一个匹配,则称$M$中边所依附的顶点是已匹配的顶点,若$P$是图$G$中一条连通两个未匹配顶点的路径,并且不属于$M$的边和属于$M$的边(即待匹配的边和已匹配边)在$P$上交替出现,则称$P$为相对于$M$的一条增广路径。如果我们将$P$的路径看着边的集合,我们令$M'=M \mathop{xor} P$,则$M'$是比$M$多一条边的匹配,即更大的匹配$M'$包含了或者属于$M$,或者属于$P$,但不同时属于$M$$P$的边。当找不到增广路的时候,则这时候的$M$是最大匹配。
假设$M$是二分图$G$的一个匹配,则称$M$中边所依附的顶点是已匹配的顶点,若$P$是图$G$中一条连通两个未匹配顶点的路径,并且不属于$M$的边和属于$M$的边(即待匹配的边和已匹配边)在$P$上交替出现,则称$P$为相对于$M$的一条增广路径。如果我们将$P$的路径看着边的集合,我们令$M'=M \mathop{xor} P$,则$M'$是比$M$多一条边的匹配,即更大的匹配$M'$包含了或者属于$M$,或者属于$P$,但不同时属于$M$$P$的边。当找不到增广路的时候,则这时候的$M$是最大匹配。
\paragraph{例题} 把光束当作图的顶点,小行星当作连接对应光束的边。
\codeinput[\href{http://poj.org/problem?id=3041}{POJ3041} - Asteroids]{assets/day7/poj3041.cpp}
\subsection{迭代加深搜索} 通过搜索的办法来判断是否有不超过某个$x$的解。把$x$$0$开始每次增加$1$,那么首次找到解时的$x$便是最优解。这种搜索就被称为迭代加深搜索(IDDFS)。如果加上状态$v$到目标状态的距离下界的估价函数$h^*(v)$进行提前剪枝优化后的算法则称为IDA*。但要保证$h^*(v)$的值小于真实的值,否则会导致错误的剪枝。
\paragraph{例题} 估价函数:还没有走到正确位置上的棋子的个数
\codeinput[\href{http://www.lydsy.com/JudgeOnline/problem.php?id=1085}{BZOJ1085} - 骑士精神]{assets/day7/bzoj1085.cpp}
\subsection{折半搜索/MITM} 从初始状态与目标状态同时出发进行搜索
\paragraph{有向图模型}
考虑这样一个问题:给定一张有向图$G$,图中所有边的长度均为$1$,现在求从图中的点$A$到点$B$之间有多少条长度为 L 的不同的路径。两条路径不同当且仅当某一步它们所走的边不相同。我们设图中点的最大出度为常数$D$\\
朴素的想法是我们从$A$开始DFS走$L$步,若最后停在了$B$点则我们可以记录进答案。这个做法的复杂度是$O(D^L)$\\
我们换个角度考虑,从点$A$到点$B$长度为$L$的路径,可以看做是点$A$到某点$u$长度为$\frac{L}{2}$的路径加上点$u$到点$B$长度为$\frac{L}{2}$的路径。\\
从点$A$正向 DFS$\frac{L}{2}$步,对每个点记$P_u$表示点$A$正向走到它的不同路径数。\\
从点$B$反向 DFS$\frac{L}{2}$步,对每个点记$Q_u$表示点$B$反向走到它的不同路径数。\\
根据加法原理与乘法原理以及上面的分析我们可知最后的答案为:$\sum\limits_u P_u \cdot Q_u$\\
容易发现,这个做法的复杂度就降为了$O(D^\frac{L}{2})$\\
这就是常用折半搜索的第一种模型,即有向图模型,从这个模型的做法我们也能看出,折半搜索是一种双向搜索。
\paragraph{方程模型}
考虑这样一个问题,给定一个整数的集合$S$,求有多少有序六元组$(a,b,c,d,e,f)$满足$a,b,c,d,e,f\in S,d\ne0$$\frac{ab+c}{d}-e=f,|S|\leq100$\\
朴素的算法是$O(|S|^6)$枚举,并按上述式子计算,判定是否符合条件。\\
我们将原式移项为$ab+c=(e+f)\times d$,此时方程两边都有$3$个元素,因此我们考虑先$O(|S|^3)$的时间枚举左边的三个元素,算出结果,再用$O(|S|^3)$的时间枚举右边的三个元素,也算出对应的结果,那么我们现在的问题是给出两个多重数集,问有多少个数同时在两个多重数集中出现了。这个问题可以使用哈希表来解决。这里我们就简单地认为哈希表插入与查询的复杂度均为$O(1)$。那么这个算法的总时空复杂度均为$O(|S|^3)$\\
这就是折半搜索第二种常用的模型,方程模型,其核心就是通过移项,将方程两边的变量数进行平衡,之后再暴力搜索每一边,所得到的的结果利用数据结构进行存储查询,或是利用其他的一些算法进行合并,从而优化复杂度。
\paragraph{算法总结}
通常折半搜索能将时间复杂度从$O(D^L)$变为$O(D^\frac{L}{2} \times\mbox{合并复杂度})$。尽管时间复杂度仍然是指数级别,但指数减小一半,在一些问题中就能使得我们在时限内出解。并且该算法实现简单,算法使用的搜索过程与朴素算法无异,合并时也只需要用到哈希表等简单的数据结构。
\end{document}
Loading…
Cancel
Save