《挑战程序设计》的一些笔记

2.5 图

  • 图的表示 掌握用邻接表建图
  • 最短路径:SPFA(队列实现,每次从队列中去除元素松弛); dijkstra(无负权边,分为两个集合,从未求出最短路径的集合中选出最小的松弛)
  • 最小生成树:kruscal(从小到大的权值遍历边,并查集实现);prim(只与顶点有关,适合稠密图)

POJ 3255

传送门

求无向图顶点1到顶点n的次短路径。同一条边可以经过多次。

书上的做法是直接将最短路径的Dijkstra算法进行修改,对于每个顶点松弛的时候不仅松弛最短路,而且松弛次短路。我个人觉得这样的做法必须得用把路径存入到priority_queue中,再逐一出队松弛,否则每次寻找要松弛的顶点的判断条件较为繁琐。
另一种方法是根据从1->n的次短路经一定是顶点1到某个顶点P的最短路+P到顶点Q+Q到顶点n(相当于多走了一条路,这里的P可能为1,Q可能为n)。所以,我们仅需做顶点1到所有其它点的单源最短路径和顶点1到所有其它点的单源最短路径,两次Dijkstra或SPFA即可。
另外,无向图里面的数组大小要开边数的两倍。以及,有些边很多的图中可能会有重复边但权值不同的情况。

POJ 3723

传送门

征募女兵N人,男兵M人,每征募一个人需要10000$。但这些男女中,存在一些关系。如果在征募一个人时,在之前征募的人中存在和ta有关系的,那么征募费用要减去这些关系值的最大值。求最小征募费用。

把人看做顶点,关系看做边,最后的答案=10000*(n+m)- 最大生成树。
在做图论的题目时要注意顶点究竟是0…n-1,还是1…n,初始化的时候要小心。

2.1 搜索

  • DFS
  • BFS
  • 栈与队列

POJ 2386

传送门

N*M的方阵,求多少连通的”W”(这里的连通可以是每个位置的八个方位,即不仅包括上下左右,还有左上、左下、右上、右下)

DFS,从每个”w”开始做DFS,每次找其八个方位的“w”,并把其用“.”代替。每个格子作为DFS的参数最多被调用一次,时间复杂度O(8*N*M)。

2.4 数据结构

  • map,set
  • queue,priority_queue,
  • 并查集

POJ 3241

传送门

卡车行驶L单位距离。一开始有P单位汽油,每单位距离需耗费1单位汽油。在路途中有一些加油站,距终点Ai的加油站能加Bi汽油,要求在这之中选取最少的一些加油站,使得能够走过全程。

优先队列,每走过1个加油站,存入一个从大到小的优先队列。然后每次走到油量为0时,取出队列的头元素。若队列为空则无法到达终点。

POJ 3253

传送门

类似于合并果子。

优先队列,O(NlogN)

POJ 1182

传送门

A吃B,B吃C,C吃A,给出K条信息,求出矛盾的。

种类并查集,喜欢书上的做法。对每只动物创建3个元素i-A,i-B,i-C,其中i-x表示“i属于种类x”,并查集里的每一个组表示组内所有元素代表的情况都同时发生或不发生。
合并前,判断是否矛盾。否则,对于A和B是同一种类的信息,合并x-A和y-A,x-B和y-B,x-C和y-C。对于A吃B的信息,合并x-A和y-B,x-B和y-C,x-C和y-A。

2.6 数学

  • 辗转相除法、扩展欧几里得
  • 素数判断、晒垡
  • 取模运算
  • 快速幂

UVA10006

传送门

简单快速幂

ZOJ 3609

传送门

求解乘法逆元,ax同余1(mod m) 等价于 ax+my=1。

扩展欧几里得的应用,本题里因为求得是最小的正整数x,所以对于x=0 的特殊情况要特判一下。

3.5 网络流

  • 最大流

    从点s传输数据到t,每条边都有最大传输量(即边的容量),求最大传输量。

    基础方法:Ford-Fulkerson,多次进行深度优先搜索寻找增广路,并更新残余网络(正向边减去这条路的流量,反向边增加),直至找不到增广路为止。
    优化算法:Dinic,每次寻找最短的增广路。每次先进行一次BFS,考虑从近距离顶点指向远距离顶点的分层图,在上面DFS寻找最短增广路。此外需要注意的是,在进行DFS时,为了避免对一条边多次检查,需要当前弧优化。

  • 二分图最大匹配

    两组顶点,组内不含边,求出最多的两两不含公共端点的边数。

    构造两个虚拟顶点s和t,然后转化为最大流问题。可以根据二分图的性质,简化代码。

  • 最小费用流

    边上增加权值的信息,求流量为f时费用的最小值。
    在残余网络上沿着最短路增广,由于有反向边,不用dijkstra求最短路,用Bellman-Ford。

poj 3469

两个处理器运行n个模块,每个模块在处理器A或B上执行都有所需的花费Ai或Bi。有m个相互之间需要数据交换的模块组合(ai,bi),如果在不同的处理器上会有额外花费wi。求执行所有模块的最小值。
在处理器A上执行的模块集合为S,在B上为T。从起点s向每个模块连一条Bi的边,从每个模块向终点连一条Ai的边,从ai向bi连一条wi的双向边。最大流。

poj 3281
共有F种食物,D种饮料。每头牛都有自己喜爱的食物和饮料,每种食物只能分配给一头牛,求最多有多少头牛能同时获得喜欢的食物和饮料。
建图,s->食物->牛->牛->饮料->t,即从s到所有的食物连一条边,从食物向喜爱它的牛连边,牛本身连一条边,牛到相应喜爱的饮料连边,饮料到t连边。求最大流。

poj3041

n*n网格,k行星。一束光能消灭一整行或整列,求最少需要多少道光能全部消灭。
一共2N个光束选择(行N个,列N个)。把光束看做图的顶点,行星看做连接对应光束的边,最后的要求是求最小的顶点集合,是的每条边至少有一个光束中的顶点。
最小顶点覆盖,转化为二分图最大匹配。

poj 3686

n个玩具,由m个工厂加工。a[i,j]表示第i个玩具由第j个工厂加工的时间,每个工厂只能一个接一个加工玩具,求完成所有玩具时间的最小值。
若只有1个工厂,按照顺序a1,a2…,T=N*a1+(N-1)*a2+…+1*an。把每个机器拆成N个点,1~N分别代表某个玩具在这个机器上倒数第几个被加工。求最小费用流。

你可能感兴趣的:(算法)