算法_关于图的应用的思考与总结

最小生成树MST

Prim算法

  1. 从指定的一个顶点开始构建生成树;
  2. 不断将与当前生成树顶点集合距离最近的新顶点(和其相应的边)加入,直到所有顶点都加入
  3. 时间复杂度 O ( V 2 ) O(V^2) O(V2)

Kruskal算法

  1. 从权值最小的边开始构建生成树,不用指定;
  2. 不断将与 权值最小的边且其两头依附的顶点未连通的边(和其依附的顶点)加入,直到所有顶点都连通
  3. 时间复杂度 O ( E ∗ l o g 2 E ) O(E*log_2{E}) O(Elog2E)

最短路径

DijKstra算法

  1. 单源最短路径算法,从指定的一个源点出发,计算图中其余各个顶点到该点的最短路径dist[];
  2. 遍历所有顶点,每次将dist[i]最小而未确定最短路径的顶点,确认为最短路径找到状态final[i]=true,并重新计算该顶点相邻点的dist[j](计算未确定最短路径的顶点的最短路径长度dist[j]); 若 d i s t [ j ] + a r c s [ j ] [ k ] < d i s t [ k ] dist[j] + arcs [ j ] [k] <dist [k] dist[j]+arcs[j][k]dist[k],则更新 d i s t [ k ] = d i s t [ j ] + a r c s [ j ] [ k ] dist [k] =dist [ j ] +arcs [ j ] [k] dist[k]=dist[j]+arcs[j][k]
  3. 类似于Prim算法,不过Prim是用于计算生成树最小的边权值之和,而Dijikstra是用于计算源点到其它顶点的最短路径;
  4. DijKstra算法不允许图中带有负权值的边;
  5. 时间复杂度 O ( V 2 ) O(V^2) O(V2)

Floyd算法

  1. 多源汇最短路径算法,可以得出任意两个顶点之间的最短路径,所以需要用邻接矩阵形式存储A[i][j];
  2. 将n个结点都作为中转顶点,尝试计算所有顶点对绕行k结点时的最短路径 A ( k ) [ i ] [ j ] A^{(k)} [i][j] A(k)[i][j](绕行序号不大于k,动态规划思想不断用小问题去解决大问题);每绕行一个顶点,就是迭代一次,迭代n次后就能得到最终的多源汇最短路径;
  3. 用path[i][j]存储两个顶点之间最短路径的中转顶点编号,用于不断向上回溯最短路径顶点
  4. Floyd算法允许图中带有负权值的边,但不允许有包含带负权值的边组成的回路;
  5. 时间复杂度 O ( V 3 ) O(V^3) O(V3)

有向无环图DAG

应用1:描述含有公共子式的表达式的有效工具;

  1. 可以将表达式的二叉树中重复子式进行共享,相同功能的子式(操作数和操作符相同)只会出一次在DAG中。若表达式若多次用到该子式,就多次用箭头指向相同的结点;
  2. 画DAG的方法(分层绘制):
  • 把所有操作数放在最底层,然后计算出所有运算符的优先级(直接手动标,具体可以想象自己动手计算时的先后顺序);
  • 当运算符的其中一个操作数是子式的话,就将该运算符提高一层;
  • 画完初步运算符后,将运算符左右操作数一样的且同层的,合并为一个运算符,相关箭头都指向同一个结点

应用2:拓扑排序:

  1. 对有向无环图AOV网(用顶点表示活动Activity On Vertex)的顶点进行一种逻辑排序;
  2. 拓扑排序:每次都将没有前驱(入度为0)的顶点输出,并在网中将其对应的边删除;
  3. 逆拓扑排序:每次将没有后继(出度为0)的顶点输出,并在网中将其对应的边删除;
  4. 有向无环图的拓扑序列不唯一,不能唯一确定该图;
  5. 若每个顶点都有唯一的前驱后继关系,则拓扑排序结果唯一;若一个顶点有多个直接后继,则拓扑排序的结果通常不唯一;
  6. 用邻接表存储时的时间复杂度为 O ( ∣ V ∣ + ∣ E ∣ ) O(|V|+|E|) O(V+E);用邻接矩阵存储时的时间复杂度为 O ( ∣ V ∣ 2 ) O(|V|^2) O(V2)

关键路径

1. 基本概念

AOE网: 用边表示活动(Activity On Edge)

  1. 顶点的前驱活动都结束后,该顶点所代表的事件(时刻)才能发生
  2. 只有顶点所代表的事件(时刻)发生后,与顶点相邻的边所代表的活动才能开始

关键路径: 在AOV网中,从源点到汇点,最大路径长度的路径( 决定整个工程的最短完成时间)

最早时间:
事件的最早发生时间:前驱事件的最早发生时间与前驱活动弧的时间之和
活动的最早开始时间:活动弧的起点事件的最早发生时间
(两者相等)

最迟时间:(同一条活动弧的弧头和弧尾)
事件的最迟发生时间:后继事件的最迟发生时间与后继活动弧的时间之差
活动的最迟开始时间:活动弧的终点事件的最迟发生时间与该活动所需时间之差

活动的时间余量: 活动 a i a_i ai的最早开始时间和最晚开始时间之差
说明该活动可以拖延的时间。时间余量为0的活动,则为关键活动(说明一点都不能被拖延)
由关键活动构成的路径就是关键路径

2. 关键路径求解过程:

1. 所有事件的最早发生时间ve():

  • 对AOE网进行拓扑排序,从源点开始往后计算,令ve(0)=0
  • 逐步计算,类似动态规划思想:
    v e ( k ) = M a x { v e ( j ) + W e i g h t ( v j , v k ) } ve(k) = Max \{ ve(j)+Weight(v_j,v_k) \} ve(k)=Max{ve(j)+Weight(vj,vk)} v j v_j vj v k v_k vk的任意前驱;
    选择事件最大的前驱事件的ve(j)与前驱活动时间Weight(v_j,v_k)之和,作为事件v_k的最早发生时间;最后依次得到所有事件的最早发生时间;因为只有事件的所有前驱活动都完成了,事件才能真正发生,因此最早事件发生时间取决于最大的前驱活动时间;

2. 所有事件的最晚发生时间vl():

  • 对AOE网进行逆拓扑排序,从汇点开始往前计算,令vl(汇点)=ve(汇点)
    (因为不能推迟整个工程时间,所以工程结束时间不变);
  • 也是逐步计算的思想:
    v l ( k ) = M i n { v l ( j ) − W e i g h t ( v k , v j ) } vl(k) = Min \{ vl(j)-Weight(v_k,v_j) \} vl(k)=Min{vl(j)Weight(vk,vj)} v j v_j vj v k v_k vk的任意后继;

3. 所有活动的最早开始时间e()

  • e(i)会等于活动弧的起点事件的最早开始时间

4. 所有活动的最晚开始时间l()

  • l(i)会等于活动弧的终点时间的最晚开始时间减去该活动的时间

5. 求所有活动的时间余量d()

  • 计算每一个活动的l(i)-e(i)的时间余量,时间余量为0的活动为关键活动

3. 关键路径特性:

  1. 不能任意缩短关键活动的时间,缩短到一定程度关键活动可能变成非关键活动;
  2. AOE网中有多条关键路径时,想要提高关键活动的速度以此加速工程整体速度,需要对包括在所有关键路径中的关键活动进行加速才能够加速整体。
  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值