![](https://img-blog.csdnimg.cn/20201014180756925.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
算法竞赛入门经典
文章平均质量分 84
紫书学习笔记
Alex Su (*^▽^*)
清华大学计算机系硕士在读 ACM-ICPC银牌 CCPC银牌 蓝桥杯国一 天梯赛国一 CSP全国前50
展开
-
紫书 习题11-11 UVa 1644 (并查集)
这道题感觉思路非常巧妙, 我是看了别人的博客才想明白的。这里用到了并查集, 以根节点为中心城市, 然后把边从大到小排序, 每次的当前的边即为容量,因为是目前的最小值, 然后去算总的容量, 每次选容量大的点作为新的根节点, 也就是新的中心城市。细节见代码。#include<cstdio>#include<algorithm>#define REP(i, a, b) for...原创 2018-06-14 18:14:00 · 145 阅读 · 0 评论 -
紫书 习题 11-9 UVa 12549 (二分图最小点覆盖)
用到了二分图的一些性质, 最大匹配数=最小点覆盖 貌似在白书上有讲还不是很懂, 自己看着别人的博客用网络流写了一遍反正以后学白书应该会系统学二分图的,紫书上没讲深。目前就这样吧。#include<cstdio>#include<vector>#include<cstring>#include<queue>#include<algorit...原创 2018-06-22 18:31:28 · 118 阅读 · 0 评论 -
紫书 习题 11-15 UVa 1668 (图论构造法)
参考了http://www.bubuko.com/infodetail-1276416.html首先是逆向思维, 向把每条边看作一条路径, 然后再去合并然后我们讨论怎么样合并时最优的我们讨论当前的点u那么首先直观感受, 因为如果要合并一次, 就需要两条边,所以最多可以合并的不会超过度数(与其相连的边的总权值)的一半。但这只是直观感受, 并不是所有的情况都可以合并的了这么多。当与当前点相连的边中有一...原创 2018-06-23 15:56:34 · 290 阅读 · 0 评论 -
紫书 习题 11-8 UVa 1663 (最大流求二分图最大基数匹配)
很奇怪, 看到网上用的都是匈牙利算法求最大基数匹配紫书上压根没讲这个算法, 而是用最大流求的。难道是因为第一个人用匈牙利算法然后其他所有的博客都是看这个博客的吗?很有可能……回归正题。题目中只差一个数字的时候可以匹配, 然后求最少模板数。那么肯定匹配的越多就越少, 也就是求最多匹配多少。这个时候我就想到了二分图最大基数匹配。那么很容易想到可以匹配的一组之间就连一条弧。但问题是怎么分成两类??分类的...原创 2018-06-16 17:04:37 · 244 阅读 · 0 评论 -
紫书 习题 11-4 UVa 1660 (网络流拆点法)
这道题改了两天……因为这道题和节点有关, 所以就用拆点法解决节点的容量问题。节点拆成两个点, 连一条弧容量为1, 表示只能经过一次。然后图中的弧容量无限。然后求最小割, 即最大流, 即为答案。固定一个源点, 然后枚举汇点, 然后求最小的最小割就ok了。这里的拆点法连边的时候是拆出来的点连上原来的点。同时起点是起点拆出来的点终点是原来的点, 因为这起点和终点是可以经过很多次的。所以总结一下拆点法(解...原创 2018-06-12 18:50:51 · 134 阅读 · 0 评论 -
紫书 例题 11-13 UVa 10735(混合图的欧拉回路)(最大流)
这道题写了两个多小时……首先讲一下怎么建模我们的目的是让所有点的出度等于入度那么我们可以把点分为两部分, 一部分出度大于入度, 一部分入度大于出度那么显然, 按照书里的思路,将边方向后,就相当于从出度大于入度的运一个流量到入度大于出度的点。紫书 例题 11-13 UVa 10735(混合图的欧拉回路)(最大流)所以我们可以把源点S到所有出度大于入度的点连一条弧, 弧的容量是出度-入度的一半为什么容...原创 2018-06-18 15:19:58 · 214 阅读 · 0 评论 -
紫书 例题 11-12 UVa 1515 (最大流最小割)
这道题要分隔草和洞, 然后刘汝佳就想到了“割”(不知道他怎么想的, 反正我没想到)然后就按照这个思路走, 网络流建模然后求最大流最小割。分成两部分, S和草连, 洞和T连外围的草和S连一条无穷大的弧, 表示不能割, 若原来是洞就改成草然后加上花费。然后非外围的草和S连一条容量为把草变成洞花费的弧, T同理。然后相邻的格子之间连容量为围栏的弧。最后是要把草和洞隔开, 所以求最小割就好了。ps:这个建...原创 2018-06-17 10:40:41 · 302 阅读 · 0 评论 -
紫书 例题 11-6 UVa 658 (状态压缩+隐式图搜索+最短路)
这道题用到了很多知识点, 是一道好题目。 第一用了状态压缩, 因为这里最多只有20位, 所以可以用二进制来储存状态 (要对数据范围敏感), 然后涉及到了一些位运算。 第二这里是隐式图搜索, 和之前有一道bfs倒水的有点像, 就是题目和图论没有半毛钱关系, 但是却可以自己建图来做, 把状态看作点, 把状态转移看作边。 第三因为求最短时间, 所以用了堆优化dijsktra。#incl...原创 2018-05-25 21:32:29 · 136 阅读 · 0 评论 -
紫书 习题 11-2 UVa 1001 (Floyd)
这道题只是在边上做一些文章。这道题起点终点可以看成半径为0的洞, 我是直接加入了洞的数组。边就是两点间的距离减去半径, 如果结果小于0的话, 距离就为0, 距离不能为负然后我看到n只有100, 范围很小, 虽然这道题只是单源最短路,但是Floyd代码比较短, 而又不会超时, 所以我就写了Floyd。#include<cstdio>#include<algorithm>#...原创 2018-05-29 18:28:20 · 103 阅读 · 0 评论 -
紫书 习题 11-3 UVa 820 (最大流裸题)
注意这道题是双向边, 然后直接套模板就ok了。#include<cstdio>#include<algorithm>#include<vector>#include<queue>#include<cstring>#define REP(i, a, b) for(int i = (a); i < (b); i++)usin...原创 2018-05-29 18:56:54 · 120 阅读 · 0 评论 -
紫书 习题 11-16 UVa 1669(树形dp)
想了很久, 以为是网络流最大流, 后来建模建不出来, 无奈。后来看了 https://blog.csdn.net/hao_zong_yin/article/details/79441180感觉思路很巧妙。首先题目等价于让每条边经过的次数最多。那么假设一条边点a到点b, 假设以b为根节点的子树中的节点数为pb, 那么剩下的以以b为根节点的子树中的节点数为pa我们假设pa > pb那么从a这边去...原创 2018-06-23 11:52:20 · 175 阅读 · 0 评论 -
紫书 例题 11-3 UVa 1151 (有边集的最小生成树+二进制枚举子集)
标题指的边集是说这道题的套餐, 是由几条边构成的。思路是先做一遍最小生成树排除边, 因为如果第一次做没有加入的边, 到后来新加入了很多权值为0的边,这些边肯定排在最前面,然后这条边的前面的那些边肯定都要再扫一遍, 也就是这条边无论如何都不会选。那么后来就是二进制枚举套餐, 从头开始, 加入套餐中的边然后权值加上套餐的权值, 然后把之前筛选下来的边做kruskal就ok了。注意要对数据范围敏感, 这...原创 2018-05-22 18:34:24 · 170 阅读 · 0 评论 -
紫书 例题 11-5 UVa 10048 (Floyd求最大权值最小的路径)
这道题是Floyd的变形改成d[i][j] = min(d[i][j], max(d[i][k], d[k][j]))就好了。#include<cstdio>#include<algorithm>#define REP(i, a, b) for(int i = (a); i < (b); i++)using namespace std;const int M...原创 2018-05-25 19:33:05 · 224 阅读 · 0 评论 -
紫书 习题 11-17 UVa 1670 (图论构造)
一开始要符合题目条件, 那么肯定没有任何一个点是孤立的, 也就是说没有点的度数是1所以我就想让度数是1的叶子节点相互连起来。然后WA然后看这哥们的博客https://blog.csdn.net/trote_w/article/details/79504280原来连叶子的时候, 有三个叶子的时候, 中间的留到下一次连,左右连起来。我之前是直接按照顺序连。按照顺序那么边可能会封闭在一颗子树里面, 比如...原创 2018-06-16 10:32:22 · 155 阅读 · 0 评论 -
紫书 例题11-11 UVa 12661 (dihkstra变形)
这道题主要比较权值的时候要改变一下,其他地方基本一样。比较权值的时候要考虑边的时间与a, b可以设相对于当前边的时间now, 则now = d[u] % (a+b), 也就是当前这个边进行到整个a和b的循环的哪个地方了。然后我们分类讨论。(1)当t 〉a的时候, 这种边在输入的时候就可以去掉了, 因为不管什么情况都走不了。打开的时间不足以通过(2)可以直接过的时候。这个时候now + t <...原创 2018-05-28 18:55:54 · 123 阅读 · 0 评论 -
紫书 例题11-10 UVa 1349 (二分图最小权完美匹配)
二分图网络流做法(1)最大基数匹配。源点到每一个X节点连一条容量为1的弧, 每一个Y节点连一条容量为1的弧, 然后每条有向边连一条弧, 容量为1, 然后跑一遍最大流即可, 最大流即是最大匹配对数(2)最小(大)权完美匹配(每个点都被匹配到)。和最大基数匹配类似, 只是有向边的权值就是费用, 其余弧费用为0.跑一遍最小费用流。最后要判断从s出发的弧是否满载, 不是则不能完美匹配。如果求最大权那么费用...原创 2018-05-27 15:19:16 · 408 阅读 · 0 评论 -
紫书 例题11-7 UVa 753 (网络流最大流)
设一个源点, 到所有设备连一条弧, 容量为1, 然后设一个汇点, 所有插座到汇点连弧, 容量为1, 然后转换器也连一条弧, 容量为1。 最后最大流就是答案。其中注意节点数要开大一些。#include<cstdio>#include<queue>#include<iostream>#include<vector>#include<algo...原创 2018-05-26 20:07:23 · 134 阅读 · 0 评论 -
紫书 习题 11-1 UVa 821 (Floyd)
水题, Floyd一遍就完了。#include<cstdio>#include<algorithm>#define REP(i, a, b) for(int i = (a); i < (b); i++)using namespace std;const int MAXN = 101;int d[MAXN][MAXN], n;int main(){ ...原创 2018-05-29 17:54:08 · 156 阅读 · 0 评论 -
紫书 例题 11-14 UVa 1279 (动点最小生成树)(详细解释)
这道题写了好久……在三维空间里面有动的点, 然后求有几次最小生成树。其实很容易发现, 在最小生成树切换的时候,在这个时候一定有两条边相等,而且等一下更大的那条边在最小生成树中,等一下更小的边不再最小生成树中。这样的话过了这个时刻,等一下更小的边就会代替等一下更大的边, 从而最小生成树切换然后我们讨论怎么实现第一步, 建边因为这里边的长度是随时间变化的, 所以我们可以把其写成一个二次函数。那么显然根...原创 2018-06-17 16:27:32 · 240 阅读 · 0 评论 -
紫书 习题 11-7 UVa 10801 (单源最短路变形)
把每个电梯口看作一个节点, 然后计算边的权值的时候处理一下, 就ok了。#include<cstdio>#include<vector>#include<queue>#include<cmath>#define REP(i, a, b) for(int i = (a); i < (b); i++)using namespace std...原创 2018-06-16 14:31:13 · 140 阅读 · 0 评论 -
紫书 习题 11-10 UVa 12264 (二分答案+最大流)
书上写的是UVa 12011, 实际上是 12264参考了https://blog.csdn.net/xl2015190026/article/details/51902823这道题就是求出一种最优的移动士兵的方式, 使得与敌方相邻的阵营中最少的士兵最多因为只能在我方的阵营中移动士兵, 所以建模的时候不用加入地方阵营的点。首先因为士兵只能移动一次, 所以把点拆成两个点, 入点和出点。设阵营士兵的人...原创 2018-06-22 20:44:39 · 195 阅读 · 0 评论 -
紫书 例题 11-1 UVa 12219 (表达式树)
这道题看了刘汝佳的代码真的是天秀, 很值得学习。具体看代码#include<cstdio>#include<iostream>#include<cctype>#include<map>#define REP(i, a, b) for(int i = (a); i < (b); i++)using namespace std;con...原创 2018-05-20 11:52:42 · 221 阅读 · 0 评论 -
紫书 例题11-8 UVa 11082(网络流最大流)
这道题的建模真的非常的秀, 非常牛逼。先讲建模过程。源点到每一行连一条弧, 容量为这一行的和减去列数, 然后每一列到汇点连一条弧, 容量为这一列的和减去行数, 然后每一行和列之间连一条弧, 容量为19。然后求最大流, 最后矩阵中每一个元素的值就是其所在列和行所连的弧的容量加1.让我来解释一下。设每一个行为xi, 每一列为yi。在网络流中, 每一个xi都有多条弧连到所有的yi, 在矩形当中每一行的每...原创 2018-05-27 10:39:17 · 150 阅读 · 0 评论 -
紫书 例题 11-2 UVa 1395(最大边减最小边最小的生成树)
思路:枚举所有可能的情况。枚举最小边, 然后不断加边, 直到联通后, 这个时候有一个生成树。这个时候,在目前这个最小边的情况可以不往后枚举了,可以直接更新答案后break。 因为题目求最大边减最小边最小, 在最小边确定的情况下, 要使得差值最小, 就要使得最大边最小, 那么排序之后加边后的第一个生成树一定是此情况下的最优解, 因为这个时候最大边最小, 后面的边肯定更大。细节(1)注意题目给的点标号...原创 2018-05-21 18:48:14 · 234 阅读 · 0 评论 -
紫书 例题11-9 UVa 1658 (拆点+最小费用流)
这道题要求每个节点只能经过一次,也就是结点容量为1, 要拆点, 拆成两个点, 中间连一条弧容量为1, 费用为0.因为拆成两个点, 所以要经过原图中的这个节点就要经过拆成的这两个点, 又因为这两个点的边的容量为1, 所以只能经过一次, 就等价于原图中的点只能经过一次。拆点的时候要注意细节:起点和终点不用拆, 因为有两条路径, 所以起点和终点必须经过两次。因此一开始的时候只拆2到n-1这些点, 拆成i...原创 2018-05-27 12:16:03 · 141 阅读 · 0 评论 -
紫书 例题11-4 UVa247 (Floyd判断联通)
Floyd联通, 然后为了输出联通分量而新建一个图, 让互相可以打电话的建立一条边, 然后dfs输出联通分量就ok了。#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<map>#include<vector>#de...原创 2018-05-24 18:54:48 · 156 阅读 · 0 评论 -
紫书 习题 11-12 UVa 1665 (并查集维护联通分量)
这道题要逆向思维反过来从大到小枚举, 就是在矩阵中一点一点加进去数字,这样比较好操作, 如果正着做就要一点一点删除数字, 不好做。我们需要在这个过程中维护联通块的个数, 这里用到了并查集。首先加进去一个数, 联通分量数字先加一, 然后再考虑有没有和其他联通分量相连。从当前位置四个方向枚举, 如果这个数之前已经被选中, 同时不是一个联通分量, 那么也就是说当前这个木块把两个联通分量变成一个联通分量,...原创 2018-06-23 10:34:24 · 123 阅读 · 0 评论 -
紫书 习题 10-18 UVa 10837 (欧拉函数变形)
这道题很巧妙,要把式子变一下phi(n) = n * (1 - 1 / p1) * (1 - 1 / p2)……(1 - 1 / pr) = n * ((p1-1) / p1) * ((p1-2) / p2) ……((pr-2) / pr) = p1^k1 * p2^k2……pr^kr * ((p1-1) / p1) * ((p1-2) / p...原创 2018-07-26 09:31:40 · 172 阅读 · 0 评论 -
紫书 例题 10-26 UVa 11440(欧拉函数+数论)
这里用到了一些数论知识首先素因子都大于M等价与M! 互质然后又因为当k与M!互质且k>M!时当且仅当k mod M! 与M!互质(欧几里得算法的原理)又因为N>=M, 所以N!为M!的倍数所以只要求1到M!中与M!互质的数的个数,在乘上N!/M!可以理解为每一块M!有这么多,然而N!中有很多块M!,所以乘上N!/M!然后根据phifac[n] = phi[n!]...原创 2018-07-20 12:02:05 · 197 阅读 · 0 评论 -
数论模板
#define REP(i, a, b) for(int i = (a); i < (b); i++)#define _for(i, a, b) for(int i = (a); i <= (b); i++) 欧几里德算法(辗转相除法)(1)可以用来求最大公约数和最小公倍数(2)注意题目的数据是否在int内,中间结果有溢出的可能, 根据情况开long long(...原创 2018-06-28 18:07:29 · 238 阅读 · 0 评论 -
紫书 例题 10-10 UVa 10491(概率计算)
公式很好推,没什么难度#include<cstdio>using namespace std;int main(){ double a, b, c; while(~scanf("%lf%lf%lf", &a, &b, &c)) { double ans = (a * b + b * (b - 1)) / ((a + b) * (a + b - ...原创 2018-07-16 14:28:12 · 128 阅读 · 0 评论 -
紫书 习题 10-25 UVa 1575 (有重复元素的全排列+暴搜)
我一开始以为有什么很牛逼的方法来做,然后一直没有思路后来看了https://blog.csdn.net/zju2016/article/details/78562932的博客竟然是暴搜???????????/好我服了 大致思路:素数的范围在100以内因为要求尽量小,所以素数取得要尽量小在100内的素数有20多个,这20多个配合上幂是可以凑到2的63次方那么大的那...原创 2018-07-27 12:06:52 · 350 阅读 · 0 评论 -
紫书 例题 10-29 UVa 1642(最优连续子序列)
这类求最优连续子序列的题一般是枚举右端点,然后根据题目要求更新左端点,一般是nlogn,右端点枚举是n,左端点是logn难点在于如何更新左端点用一些例子试一下可以发现每次加进一个新元素的时候前面的元素都要再取一遍gcd然后gcd同的时候i尽量大为了去重,我们需要排序,用相邻元素比较保留下来最优的一些区间,然后更新答案#include<cstdio>...原创 2018-07-20 16:11:30 · 151 阅读 · 0 评论 -
紫书 习题 10-2 UVa 808(建立坐标+找规律)
这次是我遇见过最迷的一次我写的程序uDebug全过和ac程序对拍也过,求出来的坐标是一模一样的,最后结果输出的方式也是一样的交上去就是错的迷第一次遇到这种情况大佬在哪里#include<cstdio>#include<cmath>#define REP(i, a, b) for(int i = (a); i < (b); i++)u...原创 2018-07-22 11:31:37 · 212 阅读 · 0 评论 -
紫书 例题 10-3 UVa 10375 (唯一分解定理)
这道题感觉非常的秀因为结果会很大,所以就质因数分解分开来算非常的巧妙!#include<cstdio>#include<vector>#include<cstring>#include<cmath>#define REP(i, a, b) for(int i = (a); i < (b); i++)using namespace st...原创 2018-07-10 21:13:19 · 128 阅读 · 0 评论 -
紫书 习题 10-3 UVa 1643(计算几何 叉乘)
直观感觉对角线重合的时候面积最大然后可以根据方程和割补算出阴影部分的面积注意知道两点坐标,可以求出与原点形成的三角形的面积用叉乘,叉乘的几何意义以这两个向量为边的平行四边形的面积所以用叉乘除以2就可以(x1, y1), (x2, y2),叉乘为x1y2-y1x2#include<cstdio>#include<cmath>#include<...原创 2018-07-23 11:21:58 · 172 阅读 · 0 评论 -
紫书 例题 10-17 UVa 1639(数学期望+分数处理+处理溢出)
设当前有k个,那么也就是说拿到其他图案的可能是(n-k)/n那么要拿到一个就要拿n/(n-k)次所以答案就是n(1/n + 1/(n-1) ......1/2 + 1 / 1)看起来很简单,但是实现有很多细节一开始我是写了一个分数加法的函数然后发现中间过程会溢出所以要做两个操作(1) 分母为1和n不算,最后算整数部分再加上去因为如果算的话就要乘进去,分母会溢出...原创 2018-07-18 12:17:22 · 98 阅读 · 0 评论 -
紫书 习题 10-4 UVa 1644(素数筛)
素数筛没什么好说的#include<cstdio>#include<vector>#include<cstring>#define REP(i, a, b) for(int i = (a); i < (b); i++)using namespace std;const int MAXN = 2123456;bool is_prime[M...原创 2018-07-22 11:43:01 · 136 阅读 · 0 评论 -
紫书 习题 10-21 UVa 1649 (组合数)
C(n, k) = m, 固定k,枚举k这里用到了组合数的一个性质当k固定的时候,C(2 * k, k) 最小 C(m, k)最大(对于这道题而言是这样,因为大于m 就最终答案不可能为m了)所以就二分去枚举2*k到m之间了。最后注意算组合数的时候超过m可以直接返回,同时比较时候可能会超出long long有小技巧可以避免,看代码。#include<cstdio&...原创 2018-07-26 14:24:32 · 178 阅读 · 0 评论 -
紫书 例题 10-16 UVa 12230(数学期望)
感觉数学期望的和化学里面求元素的相对原子质量的算法是一样的就是同位素的含量乘上质量然后求和得出这道题因为等待时机是0到2*l/v均匀分配的,所以平均时间就是l/v再加上过河的l/v, 最后加上步行的时间就ok了#include<cstdio>#define REP(i, a, b) for(int i = (a); i < (b); i++)using na...原创 2018-07-18 09:22:12 · 85 阅读 · 0 评论