##Floyed
时间复杂度:$O(N^3)$
1 |
|
##Dijkstra
时间复杂度$O(Nlog_2N)$
复杂度低且稳定,但不能处理负边权图,最重要的是手写堆优化的Dijkstra洋洋洒洒上百行,易写错
其实Dijkstra与SPFA十分相似,只是Dijkstra通过贪心法减少了不必要的松弛操作
思路:
- struct dat中存一个节点的目前最小路径长度和节点的标号
- 以dat为元建立小根堆
- 每次从小根堆取出一个不在S中的节点u,根据小根堆的性质,可以保证u是当前不在S中的点中最短路长度最小的点
- 搜索与其相邻的不在S中的点进行松弛、入堆
- 对每个节点进行过对u的此操作后,dis数组即为从v0出发到每个点的最短路
注意:#include<
queue>
bool operator<(const HN & ot)
const{return v>ot.v;}
代码:
1 | struct E{int to,next,value;} e[MAXM+1];int ecnt,G[MAXN+1]; |
##SPFA
时间复杂度:$O(NM)$
不太稳定,但能处理负边权图
1 | struct E{int to,next,value;} e[MAXM+1];int ecnt,G[MAXN+1]; |
##应用
说到最短路的应用,那简直是图论题目生产的支柱产业,甚至许多省选及以上难度的题目中也有最短路的影子。
参考:对偶图及其应用(最大流、最小割转化最短路)、图论中的二分(二分和最短路结合)、分层图(将会改变的图分层后跑最短路)
题目描述
物流公司要把一批货物从码头 A 运到码头 B 。由于货物量比较大,需要 n 天才能运完。货物运输过程中一般要转停好几个码头。物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪。由于各种因素的存在,有的时候某个码头会无法装卸货物。这时候就必须修改运输路线,让货物能够按时到达目的地。但是修改路线是一件十分麻烦的事情,会带来额外的成本。因此物流公司希望能够订一个 n 天的运输计划,使得总成本尽可能地小。
输入格式
第一行是四个整数 n ( $1\leq n\leq100$ )、 m ( $1\leq m\leq20$ )、 K 和 e 。 n 表示货物运输所需天数, m 表示码头总数, K 表示每次修改运输路线所需成本。接下来e行每行是一条航线描述,包括了三个整数,依次表示航线连接的两个码头编号以及航线长度( $>0$ )。其中码头 A 编号为 1 ,码头 B 编号为 m 。单位长度的运输费用为 1 。航线是双向的。再接下来一行是一个整数 d,后面的 d行 每行是三个整数 P ( $1 < P < m$ )、 a 、 b ( $1\leq a\leq b \leq n$ )。表示编号为 P 的码头从第 a 天到第 b 天无法装卸货物(含头尾)。同一个码头有可能在多个时间段内不可用。但任何时间都存在至少一条从码头 A 到码头 B 的运输路线。
输出格式
包括了一个整数表示最小的总成本。总成本=n天运输路线长度之和+K*改变运输路线的次数。
本题的状态转移方程十分好想: $f[i]=min{f[j]+cost[j+1][i]+K},\ j\in[0,i)$
边界条件: $f[0]=-K$ (因为实际上 $j=0$ 时无需支付 $K$ )
其中 $cost[i][j]$ 表示从第 $i$ 天到第 $j$ 天不变换航线需要的成本,这里需要用对每个 $i\in[1,n],j\in[i,n]$ 求一次最短路。
1 |
|
摧毁道路 destroy
给出一张 $n$ 个点 $m$ 条边的边权均为 $1$ 的无向图,求在保证 $dis(s_1,t_1)\leq l_1$ 且 $dis(s_2,t_2)\leq l_2$ 的前提下最多能删除的边数。
$n,m\leq3000$
我们希望在满足条件的情况下使用的边数最小,如果只有一对源汇点的话取最短路即可,但有两对的情况下不能简单相加,因为两个路径的公用边只需要计算一次。考虑枚举两个中转点 $u,v$ ,这两点之间的路径是公用的,则最少的边数即为 $dis(s_1,u)+dis(v,t_1)+dis(s_2,u)+dis(v,t_2)+dis(u,v)$ 和 $dis(s_1,u)+dis(v,t_1)+dis(s_2,v)+dis(u,t_2)+dis(u,v)$ 中的最小值,注意判断是否符合条件,时间复杂度 $O(n^2)$
1 |
|