最短路
Dijkstra
详见之前的题目:https://blog.csdn.net/qq_44761480/article/details/99683285
Floyd
记住一定要把k放到最外层
int dis[MaxV][MaxV]; //代表顶点i和j的最短距离
int n,m; //顶点数n和边数m
void Floyd(){
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(dis[i][k]+dis[k][j]<dis[i][j] dis[i][k]!=INF && dis[k][j]!=INF){
dis[i][j]=dis[i][k]+dis[k][j]; //找到更短的路径
}
}
}
}
}
最小生成树
Prime算法
与Dijkstra算法的思路几乎完全一致,是让一棵小树长大,下面是伪代码
时间复杂度为 O ( V 2 ) O(V^2) O(V2),使用堆优化可以变成 O ( V ∗ l o g V + E ) O(V*logV+E) O(V∗logV+E)。
//G为图;数组d为顶点与集合S的最短距离
Prim(G,d[]){
初始化
for(循环n次){
u=使d[]最小的还未访问的结点;
记u为已访问;
for(从u出发能到达的所有顶点v){
if(vis[v]==false && d[u]+G[u][v]<d[v]){
更新d[v];
}
}
}
}
Kruskal算法
采用了边贪心的策略:
- 对所有边从小到大排序。
- 按边权从小到大测试,如果所连接的两个结点不在同一个联通块(可以用并查集),则把这条边加入当前最小生成树中(将两个并查集合并);否则将边舍去。
- 直到最小生成树边数等于所有结点数-1,或者测试完所有边,算法结束。
时间复杂度是 O ( E ∗ l o g E ) O(E*logE) O(E∗logE),显然适合顶点较多,边数较少的情况。
拓扑排序
对有先后顺序的课程进行排序,可以抽象为一下的步骤:
- 定义一个队列Q,把所有入度为0的结点加入队列。
- 取队首结点输出,并令其连接的所有结点入度减一。
- 将入度为0的结点加入队列。
- 反复执行2、3,直到队列为空。
如果输出结点为N,则为有向无环图。
topologicalSort很重要的应用就是判断有向无环图。如果有多个入度为0的点,要求选择编号最小的,可以使用优先队列或者set。
关键路径
求工程中每个结点的最早开始时间,最晚开始时间。