一、最小生成树
1.1 概念
- 一个连通图生成树必须包含所有顶点,并且含尽可能少的边。
- 对于生成树来说,砍掉一条边,变成非连通图;增加一条边,变成回路
1.2 性质
- 最小生成树不是唯一的(树的形状不唯一);
- 最小生成树的边的权值之和总是唯一的;
- 最小生成树的边数为顶点数减一;
1.3 Prim算法
- 该算法类似于Dijkstra算法
- 思想:
- ①先选一个顶点加入树T;
- ②选一个与当前树T最近的顶点(边需权值最小)
- ③重复①②以此类推
- 总结:点边点,选一个点然后选最近权值最小的边。
1.4 Kruskal算法
- 该算法是一种按权值递增次序选择合适的边来构造生成树
- 思想:
- ①初始看成n个顶点
- ②不断随机未被选取且权值最小的边
- ③形成若干个不同连通分量,最终变为一个连通分量
- 总结:边点边,选最小的连通分量加入树
二、最短路径
最短路径问题主要分单源最短路径和各顶点之间的最短路径;
前三个BFS算法和Dijkstra算主要解决单源最短路径,Floyd算法主要解决每个顶点之间的最短路径问题
2.1 BFS算法
-
只适用于无向图
-
材料:
- d[ ]数组:记录V0到别的点的权值;初始第一个V0 = 0;
- path[ ]数组:初始为-1,记录访问的结点的前驱
-
思想:
- 借用广度优先遍历的思想,也就是树的层序遍历
- 借用广度优先遍历的思想,也就是树的层序遍历
-
伪代码
//从顶点u到其他顶点的最短路径
void BFS_MIN_Distance(Graph G,int u){
//d[i]表示从u到i结点的最短路径
for(i = 0;i<G.vexnum;++i){
d[i]=∞;//初始化路径长度
path[i] =-1;//最短路径从哪个顶点过来
}//for
d[u] = 0;
visited[u] =TRUE;
EnQueue(Q,u);
while(!isEmpty(Q)){ //BFS算法主过程
DeQueue(Q,u); //队头元素u出队
for(w=FirstNeighbor(G,v);W>=0;W=NextNeighbor(G,v,w)){
if(!visited[w]){ //w为v的尚未访问的邻接顶点
d[w] = d[u]+1; //路径长度+1
path[w]=u; //最短路径应从u到w
visited[w] =TRUE;//设已访问标记
EnQueue(Q,w);//顶点w入队列
}//if
}//for
}
}
2.2 Dijkstra算法
- 材料:
- final[ ]数组:标记是否已经找到
- path[ ]数组:前驱结点
- dist[ ] 数组:最短路径长度
- 思想:
- ①初始化:找到V0(第一个结点),更新final[ ]数组为true;path[ ]数组设置为-1;
- ②循环:遍历dist[ ]数组,找到dist值最小的,且final为false的值,将其final设为true;
- ③检查所有与vi相邻的顶点,更新表中final为false结点的disk和path的值
- 复杂度:O(n²)即边的平方
- 不适用于负权值的带权图
2.3 Floyd算法
2.4 有向无环图
有向无环图:若一个有向图中不存在环,就是有向无环图,建成DAG图
三、拓扑排序
3.1 AOV网
用DAG图表示一个工程,其顶点表示活动,用有向边<Vi,Vj>表示活动Vi必须先于活动Vj进行这样一种关系,则将这种有向图称为顶点表示活动的网络,记为AOV网。
3.2 拓扑排序性质
- 每个顶点出现且只出现一次
- 若顶点A在序列排在顶点B的前面,则在图中不存在从顶点B到顶点A的路径
- 拓扑排序是对有向无环图的一种排序
- 拓扑排序有多个
3.3 手算拓扑排序
- ①选择一个没有前驱的顶点输出
- ②从网中删除该顶点和所有以它为起点的有向边
- ③重复①②
3.4 拓扑排序代码实现
四、关键路径
4.1 AOE网
在带权有向图中,以顶点为事件,以有向边表示活动,以边上的权值表示完成该活动的开销(完成活动所需要的时间),称之为用边表示活动的网络
4.2 AOE网性质
- 只有在某顶点所代表的事件发生后,从该顶点储发的各有向边代表的活动才能开始
- 只有在进入某顶点的各有向边所代表的活动都已经结束时,该顶点所代表的事件才能发生
4.3 手算关键路径(关键)
- ① 求所有事件最早发生时间ve()【多个前驱取最大】
- ② 求所有事件最迟发生时间vl()【多个后继取最小】
- ③ 求所有活动最早发生时间e()【最早事件发生时间的尾端值】
- ④ 求所有活动最迟发生时间l()【两条弧所指的结点/事件的差值】
- ⑤ 求活动余量d()【就是③④结果相减。结果为0的路径就是关键路径】