|
|
\documentclass[]{cpp}
|
|
|
\title{省选基础算法}
|
|
|
\author{雷宇辰}
|
|
|
\begin{document}
|
|
|
\setcounter{page}{0}
|
|
|
\maketitle
|
|
|
\newpage
|
|
|
\tableofcontents
|
|
|
\newpage
|
|
|
\setcounter{page}{1}
|
|
|
\section{day1 图论}
|
|
|
\subsection{有向图强连通分量的 Tarjan 算法}
|
|
|
\paragraph{定义}
|
|
|
在\textbf{有向图$G$}中,如果两个顶点$u,v$间存在一条路径$u$到$v$的路径且也存在一条$v$到$u$的路径,则称这两个顶点$u,v$是\textbf{强连通的(strongly connected)}。如果有向图$G$的每两个顶点都强连通,称$G$是一个\textbf{强连通图}。有向非强连通图的 极大强连通子图,称为\textbf{强连通分量(strongly connected components)}。若将有向图中的强连通分量都缩为一个点,则原图会形成一个 DAG(有向无环图)。
|
|
|
\subparagraph{极大强连通子图}
|
|
|
G 是一个极大强连通子图当且仅当 G 是一个强连通子图且不存在另一个强连通子图 G’使得 G 是 G’的真子集。
|
|
|
\paragraph{Tarjan 算法}
|
|
|
定义$dfn(u)$为结点$u$搜索的次序编号,给出函数$low(u)$使得\\
|
|
|
$low(u) = min$
|
|
|
\\$\{$\\
|
|
|
\verb| |$dfn(u),$\\
|
|
|
\verb| |$low(v),$ \quad $(u,v)$为树枝边,$u$为$v$的父结点\\
|
|
|
\verb| |$dfn(v)\;$ \quad $(u,v)$为后向边或指向栈中结点的横叉边
|
|
|
\\$\}$\\
|
|
|
当结点$u$的搜索过程结束后,若$dfn(u)=low(u)$,则以$u$为根的搜索子树上所有还在栈中的结点是一个强连通分量。
|
|
|
\subparagraph{代码}$\\$
|
|
|
\codeinput[tarjan - SCC]{assets/day1/tarjan-scc.cpp}
|
|
|
\paragraph{练习题}
|
|
|
\subparagraph{
|
|
|
\href{http://poj.org/problem?id=2186}{POJ2186}/\href{http://www.lydsy.com/JudgeOnline/problem.php?id=1051}{BZOJ1051} - Popular Cows} 双倍的快乐
|
|
|
\codeinput[Popular Cows]{assets/day1/poj2186.cpp}
|
|
|
\subparagraph{\href{http://poj.org/problem?id=3180}{POJ3180} - The Cow Prom}
|
|
|
\verb|The N (2 <= N <= 10,000) cows are so excited.|
|
|
|
\codeinput[The Cow Prom]{assets/day1/poj3180.cpp}
|
|
|
\subparagraph{\href{http://poj.org/problem?id=3180}{POJ1236} - Network of Schools}
|
|
|
强连通分量缩点求出度为0的和入度为0的分量个数
|
|
|
\codeinput[Network of Schools]{assets/day1/poj1236.cpp}
|
|
|
\subsection{图的割点、桥与双连通分量}
|
|
|
\paragraph{定义}
|
|
|
\subparagraph{点连通度与边连通度}
|
|
|
在一个\textbf{无向连通图}中,如果有一个顶点集合$V$,删除顶点集合$V$,以及与$V$中顶点相连(至少有一端在$V$中)的所有边后,原图\textbf{不连通},就称这个点集$V$为\textbf{割点集合}。\\
|
|
|
一个图的\textbf{点连通度}的定义为:最小割点集合中的顶点数。\\
|
|
|
类似的,如果有一个边集合,删除这个边集合以后,原图不连通,就称这个点集为\textbf{割边集合}。
|
|
|
\subparagraph{双连通图、割点与桥}
|
|
|
如果一个无向连通图的\textbf{点连通度大于$1$},则称该图是\textbf{点双连通的(point biconnected)},简称双连通或重连通。一个图有\textbf{割点},当且仅当这个图的点连通度为$1$,则割点集合的唯一元素被称为\textbf{割点(cut point)},又叫关节点(articulation point)。一个图可能有多个割点。\\
|
|
|
如果一个无向连通图的\textbf{边连通度大于$1$},则称该图是\textbf{边双连通的(edge biconnected)},简称双连通或重连通。一个图有\textbf{桥},当且仅当这个图的边连通度为$1$,则割边集合的唯一元素被称为\textbf{桥(bridge)},又叫关节边(articulation edge)。一个图可能有多个桥。\\
|
|
|
可以看出,点双连通与边双连通都可以简称为双连通,它们之间是有着某种联系的,下文中提到的双连通,均既可指点双连通,又可指边双连通。(但这并不意味着它们等价)\\
|
|
|
双连通分量(分支):在图 G 的所有子图 G'中,如果 G'是双连通的,则称 G'为双连通子图。如果一个双连通子图 G'它不是任何一个双连通子图的真子集,则 G'为极大双连通子图。双连通分量(biconnected component),或重连通分量,就是图的极大双连通子图。特殊的,点双连通分量又叫做块。
|
|
|
\paragraph{Tarjan 算法}
|
|
|
给出函数$low(u)$使得\\
|
|
|
$low(u) = min$
|
|
|
\\$\{$\\
|
|
|
\verb| |$dfn(u),$\\
|
|
|
\verb| |$low(v),$ \quad $(u,v)$为树枝边(父子边)\\
|
|
|
\verb| |$dfn(v)\;$ \quad $(u,v)$为后向边(返祖边) 等价于$dfn(v)<dfn(u)$且$v$不为$u$的父亲结点
|
|
|
\\$\}$\\
|
|
|
\subparagraph{代码}$\\$
|
|
|
\codeinput[tarjan - BCC]{assets/day1/tarjan-bcc.cpp}
|
|
|
\paragraph{练习题}
|
|
|
\subparagraph{\href{http://poj.org/problem?id=3177}{POJ3177} - Redundant Paths}
|
|
|
将一张有桥图通过加边变成边双连通图,至少要加$\frac{leaf+1}{2}$条边。
|
|
|
\codeinput[Redundant Paths]{assets/day1/poj3177.cpp}
|
|
|
\subparagraph{\href{http://poj.org/problem?id=1523}{POJ1523} - SPF}
|
|
|
求割点与删除这个点之后有多少个连通分量
|
|
|
\codeinput[Redundant Paths]{assets/day1/poj1523.cpp}
|
|
|
\subsection{2-SAT}
|
|
|
\paragraph{定义}
|
|
|
给定一个布尔方程,判断是否存在一组布尔变量的取值方案,使得整个方程值为真的问题,被称为布尔方程的可满足性问题(SAT)。SAT问题是NP完全的,但对于一些特殊形式的SAT问题我们可以有效求解。\\
|
|
|
我们将下面这种布尔方程称为合取范式:
|
|
|
$$(a\lor b\lor c\lor\cdots)\land(d\lor e\lor f\lor\cdots)\land\cdots$$
|
|
|
其中$a,b,c,\cdots$称为文字,它是一个布尔变量或其否定。像$(a\lor b\lor c\lor\cdots)$这样用$\lor$连接的部分称为子句。如果合取范式的每个子句中的文字个数都不超过两个,那么对应的SAT问题又称为\textbf{2-SAT}问题。
|
|
|
\paragraph{解法}
|
|
|
对于给定的\textbf{2-SAT}问题,首先利用$\Rightarrow$将每个子句$(a\lor b)$改写成等价形式$(\neg a\Rightarrow b\land a\Rightarrow\neg b)$.这样原布尔公式就变成了把$a\Rightarrow b$形式的布尔公式用$\land$连接起来的形式。\\
|
|
|
对每个布尔变量$x$构造两个顶点分别代表$x$与$\neg x$。以$\Rightarrow$关系为边建立有向图。若在此图中$a$点能到达$b$点,就表示$a$为真时$b$也一定为真。因此该图中同一个强连通分量中所含的所有变量的布尔值均相同。\\
|
|
|
若存在某个变量$x$,代表$x$与$\neg x$的两个顶点在同一个强连通分量中,则原布尔表达式的值无法为真。\\
|
|
|
反之若不存在这样的变量,那么我们先将原图中所有的强连通分量缩为一个点,构出一个新图,新图显然是一个拓扑图,我们求出它的一个拓扑序。那么对于每个变量$x$,\textbf{$$x\text{所在的强连通分量(新图中的点)的拓扑序在}\neg x\text{所在的强连通分量之后}\Leftrightarrow x\text{为真}$$}就是一组合适布尔变量赋值。注意到 Tarjan 算法所求的强连通分量就是按拓扑序的逆序得出的,因此不需要真的缩点建新图求拓扑序,直接利用强连通分量的编号来当做顺序即可。
|
|
|
\paragraph{练习题}
|
|
|
\subparagraph{\href{http://poj.org/problem?id=3648}{POJ3648} - Wedding}
|
|
|
Additionally, there are several pairs of people conducting adulterous relationships (both different-sex and same-sex relationships are possible)
|
|
|
\codeinput[adulterous relationships]{assets/day1/poj3648.cpp}
|
|
|
\subparagraph{\href{http://poj.org/problem?id=3678}{POJ3678} - Katu Puzzle}
|
|
|
我什么时候做过这个题?
|
|
|
\codeinput[Katu Puzzle]{assets/day1/poj3678.cpp}
|
|
|
\subparagraph{\href{http://poj.org/problem?id=2749}{POJ2749} - Building roads}
|
|
|
杀光奶牛问题就会得到解决
|
|
|
\codeinput[Building roads]{assets/day1/poj2749.cpp}
|
|
|
\end{document} |