1. 四则运算、$\mathbf{Z}_N$ 下四则运算+幂运算复杂度;

  2. 欧几里得 GCD 递归复杂度证明;

  3. 拓展欧几里得算法求乘法逆元;

  4. 利用同余性质推算大数能否被整除;

  5. 费马小定理完整证明;

  6. 非 Carmichael 合数的费马测试证明;

  7. 对称加密、非对称加密、证书;

  8. 大师定理;

  9. 比较排序的时间下界证明($n!$ 如何确定两边界?);

  10. 快选算法在 25%-75% 判据下的时间复杂度;

  11. 矩阵算法、计数逆序(及拓展)时间复杂度推导、算法设计;

  12. 有向图中,有自环等价于存在回边的证明;

  13. DAG 中,最大 post number 意味着源点、最小 post number 意味着汇点;

    证明 DAG 中,至少有一个源点和一个汇点;

  14. 普通有向图中,最大 post number 意味着位于源点强连通部件内。但最小 post number 没有特性;

  15. 记忆:任何有向图的嵌图都是 DAG;

  16. $G$ 中的源点强连通部件是 $G^R$ 中的汇点强连通部件;

  17. 证明:

    • DFS explore 子过程若从 $u$ 开始,必然以 $u$ 及其所有可达结点遍历结束后结束(反证);

    • $G$ 的两个不同的强连通部件 $C_1,C_2$,如果有从 $C_1$ 到 $C_2$ 的边,则 $C_1$ 的最大 post number 大于 $C_2$ 的最大 post number(不是所有),证明时讨论遍历开始的位置;

    • 同第 14 条;
  18. 线性时间查找有向图强连通部件算法;

  19. 问题:

    • 线性时间找到有向图中能到达其他所有顶点的点(如果不存在需要指出);
    • 线性时间判断无向图是否为二部图:证明使用着色法;
    • 线性时间判断有向图是否存在奇数个顶点的环:每个强连通子图上 DFS 二染色。对回边(好理解)/ 前向边 / 交叉边(如果强连通部件中从 $u$ 到 $v$ 间有两条道路,并且这两条道路奇偶数不同,因为违反染色规则了所以不同。则必然存在一个奇数环和一个偶数环)违反规则的情况认为是含有奇数顶点的环;
    • 线性时间找 DAG 中从指定顶点 $u$ 到 $v$ 的路径数目:从 $u$ DFS 遍历时,遇到无论什么边,只要是指向 $v$ 的,都让计数加一;
    • 线性时间判断 DAG 中的 Hamilton 路径的存在性:修改线序化算法。每次检查是否有多于一个入度为 0 的结点,如果是就不存在。
  20. lemma:BFS 过程中,对每个 $d\in\mathbf{N}$,都总存在一个时刻,使得

    • 所有与 $s$ 间距小于等于 $d$ 的顶点都被正确地设置了距离;
    • 其他顶点的距离都还未被设置($+\infty$);
    • 队列中只含有与 $s$ 间距为 $d$ 的顶点;
  21. 分析 d-堆、二叉堆、数组作为 Dijkstra 算法的优先级队列时的时间复杂度情况;

  22. Dijkstra 算法:

    • 所有结点初始化距离为 $\infty$,只有源点是 0;然后对所有结点构建优先级队列;
    • 在队列不空时循环出队:
      • 出队 $u$ 时,更新相邻结点距离。如果更小就覆盖(此举会改变相邻点在优先级队列中的位置),并且维护最短路径列表 pre[](如果需要);

    时间复杂度:$|V|$ 次删除、$|V|+|E|$ 次 decreaseKey

  23. 证明 Dijkstra 算法正确性:归纳假设

    • 预设:对于一个图 $G$,设定源点 $s$,希望测量的目标点 $v$,假定算法运行时已经设定距离(完整更新一轮邻居后的结果)的结点的集合为 $S$。下面对 $S$ 的大小与算法正确性归纳;

    • 奠基:$|S|=1$ 的情况显然算法正确($s$ 的最短距为 0);

    • 假设:假设对于 $|S|\ge1$ 的情况算法都是正确的;

    • 归纳:进行下一轮邻居更新时,设更新到的结点 $v$ 将被加入 $S$,设 $(u,v)$ 是最后一条边。则 $s$ 至 $u$ 的最短路径一定位于 $S$ 中(算法正确性保证),记为 $dist[u]$,我们只需要证明 $dist[u]+l(u,v)$ 比其他任何 $s$ 到 $v$ 间的路径都短就行。

      • 假设 $(x,y)$ 是新一轮迭代中第一条边(最有可能更短),并且 $y$ 到 $v$ 右边。我们记 $s$ 到 $x$ 的路径为 $p^\prime$,则:

        $l(p^\prime)+l(x,y)\ge dist[u]+l(x,y)\ge dist[y]\ge dist[v]$;

        注意到,如果存在负边权,$dist[y]\ge dist[v]$ 不再成立,因为可能 $l(y,v)$ 是个绝对值很大的负数。

        这个时候如果需要更新 $v$,发现 $v$ 已经被弹出去了,没法更新了,因此 Dijkstra 算法在负权下不再是正确的了。

  24. Bellman-Ford 算法:

    • 从源点开始,同时地更新一次(不能把这轮更新的信息用来更新其他结点)每条边的两端点的距离信息;
    • 重复上述动作 $|V|-1$ 次;

    时间复杂度 $O(|V||E|)$;

  25. 证明为何 Bellman-Ford 算法只需要重复更新 $|V|-1$ 次:

    • 因为从源点 $s$ 到任意一点 $t$ 的最短路径 $s\rightarrow v_1\rightarrow v_2\rightarrow\cdots\rightarrow v_k\rightarrow t$ 最多包含了 $|V|-1$ 个顶点(这条用反证法)。
    • 更新了 $|V|-1$ 次后,即便再多的更新都是安全的($\min$ 不会变大),并且不会缺漏(顶点不会移除);
  26. 如何检测负环?让 Bellman-Ford 算法在运行 $|V|-1$ 次后再进行一次,如果还有顶点的距离在变化,则说明有负环。

  27. 可以含负权的 DAGs 的单元最短路径算法:先拓扑排序,再按线序顺序更新结点的距离信息;

    时间复杂度:$O(|V|)$;

  28. 问题:

    • 强连通图的某点 $v_0$ 通过的边全部是正权的。找任意两点间的最短路,要求必须经过 $v_0$;

      先求 $v_0$ 为源的到各点的最短距离,然后 $dist(u,v_0)+dist(v_0,v)$;

    • 无向正权图中有一条边 $e_0$,求含 $e_0$ 的最短环的长度;

      设 $e_0=(u,v)$,在 $G-e_0$ 中执行 Dijkstra 算法找到 $u$ 到 $v$ 的最短距离,加上 $l(e_0)$ 即可;

    • 有向正权图的最短环?

      环是由 $u$ 到 $v$ 和 $v$ 到 $u$ 的路径拼接而成。

      先求每两个点间的最短路径(数组数据结构 $O(|V|^3)$),在遍历查找 $dist(u,v)+dist(v,u)$ 最小值;

    • 有向正权图中最简最长路径?

      NP Hard 问题;可以将 Hamilton 图问题规约到这个问题。

    • 无向正权图的最短环?

      遍历所有边,每轮循环时删除当前边,并且选取一端运行 Dijkstra 算法。如果另一端是可达的(不是 $\infty$,记为 $c_i$),那么说明原图中存在一个长度为 $c_i+l(e)$ 的环。遍历找长度最小的那个。

    • 无向等权图中指定两点间最短路径数量?

      BFS 使用两个队列。类似 copy collection,最终在队列 1 中找到与 $u$ 相邻的结点终止。然后统计队列中还有哪些与 $u$ 相邻的结点。其数量即为所求。

      这个方法的原理是利用 BFS 的性质(参见第 20 条 lemma):在每轮结束后队列中放的是相同长度的结点(分开放能确保下一轮的结点不会混入当前队列中)。

  29. 证明 $|V|-1=|E|$ 的无向连通图等价于树数据结构;

    • 必要性:归纳。对顶点归纳的话,就是 $k$ 个顶点推 $k+1$ 个;对边归纳的话,就是向 $n$ 个顶点中加边看连通部件数是否减为 1;

    • 充分性:反证。假设不是树,则必然存在环,重复去环得到 $|E^\prime|\lt|E|$,由必要性可知 $|E^\prime|=|V|-1=|E|$,矛盾;

  30. 证明一个无向图是一棵树 当且仅当 任意两结点间有一条唯一路径;

    • 充分性:反证。如果不是就有环,违反定义;
    • 必要性:先判断是连通图,再反证。假设存在环,则存在两个结点间路径不唯一,矛盾;
  31. Kruskal:向顶点中加尽可能小的边,成环就舍去。直至加够 $|V|-1$ 条;

  32. 割定理:割集间的最短边一定在最小生成树中:分类讨论 + 反证法;

  33. Prim:顶点割集 + 顶点的策略。正确性由割定理保证;

  34. 上色算法求 MST:破圈(染红没有红边的环)、闭圈(染蓝没有蓝边的割边集合中最短边);

  35. 证明贪婪算法作为近似算法求解 set cover 问题的近似比为 $\ln n$(设 $n_t$ 是 $t$ 轮选取后剩下的顶点数);

  36. 01 背包和完全背包问题的状态转移方程、边界条件(出口)、时空复杂度;

  37. 多重背包问题(不含二进制优化)算法设计以及时间复杂度分析;

  38. 硬币找零问题最优解算法;

  39. 子序列系列问题:

    • 最长递增子序列:构造 DAG 再动归边;
    • 最长公共子序列、最长公共子串;
    • 分治法和动态规划分别求解 最大连续子序列(即子串)和(为什么讨论以 $a_i$ 结尾的子串?子串更适合这种方法!);
  40. 三分问题的状态转移方程;

  41. Shortest Reliable Path Lite:经过不超过指定边数的最短路径问题;

    和 Shortest Reliable Path 的 NP-Complete 问题不一样;

    详情参见第 50 条;

  42. 矩阵乘法最优分配:化归为二叉树,动归二叉树代价;

  43. 动态规划尝试解决 TSP 问题算法;

  44. 线性时间找出树的 independent set 大小:分类讨论,孙子结点可以在、儿子结点只能替代;

  45. 棋子放置问题:模式、相容 与动态规划;

  46. DP 难题:

    假设 $M[i,j,p,q]$ 表示对子串 $s[i]\sim s[j]$ 分割,涉及分割点在数组中 $d[p]\sim d[q]$,分割后的最小代价;

    状态转移方程:$M[i,j,p,q]=j-i+1+\min\limits_{p\le k\le q}\{M[i,d[k],p,k]+M[d[k]+1,j,k+1,q]\}$;

    算法复杂度 $O(m^2n^2)$;

    设在 $x\times y$ 的布料上制作前 $i$ 个产品的最大价值为 $P(i,x,y)$,则状态转移方程为:

    主要注意到布料是可以旋转使用的!因此分为旋转后再裁剪($P_v$)和不旋转直接裁剪($P_h$)两种手段。

  47. 规范型线性规划转对偶式;

  48. 单纯形算法时间复杂度推导 $O(n(m+n)C_{m+n}^n)$;

  49. 单纯形算法求解多元线性规划;

  50. 最大流问题变式:

    • 含有多个源点和汇点的最大流问题:定义新的源点和汇点;
    • 每个顶点有流量限制:将每个顶点拆成两个,这两个顶点间用一条有向边连接,容量就是限制。转换成普通最大流问题;
    • 每条边在容量的基础上添加限制,要求流量不得低于某个限制。或者某些节点间存在流量损耗:直接规约成一般线性规划问题;
  51. 瓶颈边(增大会导致总流增大)、临界边(减小会导致总流减小):注意它们俩是不一样的!!

  52. 查找临界边:

    • 剩余图中只有反向边的;

    • 但也不全是。可能某条在最大流中流满的边,其容量下降后,最大流中缺少的流量可以从其他边的流量得到补充。通过在剩余图中 DFS 能通过的这些反向边就不是临界边,排除它们即可。

  53. 证明:二部图的最小顶点覆盖能够被规约为最大流问题。

  54. 边不相交问题(化归为最大流问题,需要证明);

  55. 常见 NP-Complete 问题规约:

    • 稠密子图问题(a 个顶点中至少 b 条边):$b=\dfrac{a(a-1)}{2}$,从最大团问题规约;
    • 稀疏子图问题(a 个顶点中至多 b 条边):$b = 0$,从最大独立集问题规约;
    • 集合覆盖问题:从顶点覆盖规约(子问题,一个元素只会同时存在于两个集合中);
    • 子图同构问题(G 能否只通过删除一些点、边,修改名称来得到 H):从哈密顿回路规约(构造图 G 是一个 N 元环,N 为输入图的顶点数);
    • 最大公共子图(同时删除 G 和 H 一些点和对应边,使二者相同,预算 b):从最大独立集规约;
    • 哈密顿回路、哈密顿道路相互规约;
    • 最长初级路径(simple longest path):从哈密顿路径规约;
    • K-Coloring 问题:从 3-SAT 问题规约(构建 OR-gadget 和 Clause gadget);
    • 可靠网络问题(shortest reliable path,给定顶点、距离矩阵(边权)、连接需求(重边数量)、预算,构建一个总代价不超过预算、两点间的不同路径数等于对应连接需求的图):从 TSP 问题规约(预算 $b=n$,距离矩阵全为 1 或 2,表示有边和没有边,连接需求全为 2,表示在环上);
  56. 近似算法解决 NP 问题:

    • 贪婪算法求解集合覆盖问题。近似比 $ln n$;
    • 极大匹配算法(贪婪选取尽可能多的 endpoints 的边,然后删除共享 endpoints 的边)求解顶点覆盖问题。近似比 2;
    • 贪婪算法求解 k-clustering 问题:先任取一个点作为第一个中心,然后每次取离当前点最远的,中垂线分割。近似比为 2;
    • MST + skip 近似 metric-space-TSP 问题:近似大小不大于最小生成树长度两倍。而最优解不不小于最小生成树长度。因此近似比为 2;
    • rescale value 近似背包问题:缩小 $\hat{v_i}=\dfrac{n}{\varepsilon v_{\max}}$,总价值 $\sum v_i\ge\sum\hat{v_i}=K^\star(1-\varepsilon)$,即近似比为用户指定的任意接近;