• 算法与数据结构 --- 图 --- 图的应用


    第一部分 --- 最小生成树

    1.生成树的所有顶点都由边连接在一起这个条件可以理解为: 图是连通的

    2.生成树是具有 n 个顶点和 n - 1 条边的图,但是具有 n 个顶点和 n - 1条边的图不一定是生成树,比如下面这样一个图:

    首先这个图不是连通的,其次这个图中具有回路,所以这不是一棵生成树

    那么我们如何获得一个图的生成树呢?

    首先我们来讲讲无向图的生成树

    1.我们采用深度 / 广度优先搜索的方式来获得图的生成树,其中通过深度优先搜索获得的生成树称为深度优先生成树,通过广度的话则是广度优先生成树

    2.获得生成树的原理(通过遍历能够获得生成树的前提是我们遍历的是连通图而不是非连通图):我们在遍历顶点的时候会沿着图中的边遍历每一个顶点,且每个顶点都只会被遍历一次

    由于每一个顶点都只会被遍历一次,所以可以保证不会形成回路

    同时由于每一个顶点都要被遍历到,所以可以保证图是连通的(我们是沿着边进行遍历的,如果连通图中所有顶点都被遍历到的话就意味着所有顶点都靠边连接在一起,也就意味着图是连通的)

    3.综上,遍历过的顶点和遍历时经过的边组成的原图的子图就是原图的生成树

    1.网络:就是边具有权重值的图

    1.通过上面这个性质我们可以通过不断找边入点的方式来生成原图的最小生成树

    我们选择图中任意一个顶点使其进入到U集合中,然后根据上面的性质找到U集合中的顶点与V - U集合中的顶点形成的边的最小权重边,这条边一定是属于最小生成树的,我们将这条边的另一个不属于U集合的顶点放入到U集合中

    接着我们继续按照这个性质生成边(生成的边一定属于最小生成树),生成边后再按照上面的方式扩大U集合,就这样不停的扩大点集U和生成边,到最后我们就可以获得一个包含所有原图所有顶点的,连通的,没有回路的,所有边都属于最小生成树的图,而这些边又属于这个图,则显然,这个图本身就是最小生成树

     

     1.一次只能选择一条边,且选择的边不能和已有边之间形成回路

    1.这个算法的停止条件是选中的边的数目为 n - 1 (顶点数减1或者是原本的非连通图变为连通图)

    2.最小生成树可能不唯一

    1.普利姆算法中,我们选择的图中的一个顶点都需要和图中的每一个顶点匹配来判断它们之间有没有边,如果有的话权重值是不是最小,若图中有n个点的话,则最坏的情况就是n个顶点都需要被选中去匹配,则时间复杂度为 O(n*n)

    2.克鲁斯卡尔算法的思想是选择边,所以它的时间复杂度与图中的边有关,算法选择边的方式是顺序选边,时间复杂度为O(1),但是在顺序选边前需要我们将边按照权重值的大小进行排序,而排序的时间复杂度为O(e * loge)(e为边数,这个排序算法时间复杂度后面会学)

    3.对于稠密图而言,边的数目会非常大,而点的数目则不会很大,所以我们在生成稠密图的最小生成树的时候用普里姆算法

    4.对于稀疏图而言,边的数目往往小,此时可以选择克鲁斯卡尔算法


    第二部分 --- 最短路径

     

    1.最小生成树和最短路径最大的区别就是:一个涉及到图中所有的顶点,且最终会得到一棵树(图),而另一个只和图中的两个顶点有关系,最终得到的是一条路径

     

     

     

    1.如果源点V0到某个终点Vk之间没有直达路径的话,就将源点V0到终点Vk之间的路径长度记为无穷大

    2.在第三步更新中,在我们选择了当前最短路径并进行了调整之后,我们要在调整后的路径中继续选择一条长度最短的路径,并再次进行更新操作

    3.从源点到每一个顶点都存在着一条最短路径,我们先找到与源点之间存在直达路径的顶点,此时这些直达路径就是这些顶点的最短路径,我们将这些最短路径对应着顶点存好,然后对于那些与源点没有直达路径的顶点,我们认为它们到源点之间的最短路径长度为无穷大,我们也将这个无穷大存到对应的位置中

    4.设空点集S,图的除去源点的点集为V ,点集T = V -S。

    我们从T中选择一个终点u,要求源点到这个终点u的路径长度是 T 中所有顶点对应的路径长度最小的 ---如果u终点处满足更新条件的话,我们就进行路径更新,将新的路径存到对应的顶点vk处,同时将u顶点存放到集合S中

    存放完毕后我们重复第四步,直到S集合等于V集合停止重复,此时所有顶点的最短路径都被找完

    5.S集合中存放的都是已经找到最短路径的顶点,且进入点集越早的顶点最短路径越小,也就是说我们是按照最短路径递增的方式向S集合中放入顶点的

    6.在第三步中我们存好的每个顶点的最短路径中存在着两类最短路径,分别是实际最短路径和假定最短路径。其中实际最短路径就是顶点和源点之间真正的最短路径,但是假定最短路径则不是,它是我们假定的,是可以别修正。

    首先我们在一开始的所有顶点的最短路径中选择最短的那个最短的那个最短路径L,此时这个L就是它所对应的顶点的真实最短路径,证明如下:

     

    就是按照我上面的证明以及解释来运行这个算法

     

    1.首先生成图的邻接矩阵,其中对角元素都置为0(忽视掉顶点与自身的边关系),然后如果两个顶点之间具有直接边关系(邻接点),那就再矩阵对应位置填入边的权重值(邻接点),如果不具有直接边关系,则对应位置的元素改为无穷大(自己定义的数值)

    2.生成好邻接矩阵后,选择图中的一个顶点作为中间顶点插入到邻接矩阵中每个元素对应的边关系里(除了对角元素),如果插入后得到的新路径使得权重值变小了,则将原有权重值修改为新的权重值,并记录这条新的路径;如果权重值没变化的话就不做改变,当邻接矩阵中所有的元素对应的边关系都被插入一次之后,我们继续插入另一个顶点,直到图中所有顶点都插入过一次之后,算法结束


    第三部分 --- 拓扑排序 

     

     

    1. 路径是由边组成的

    2.以上面的C1到C5为例,C1和C5之间存在一条有向路径(由边组成),所以C1是C5的前驱,C5是C1的后继

    3.以C1到C4为例,C1和C4之间存在一条有向边,所以C1是C4的直接前驱,C4是C1的直接后继

    4.如果AOV网中存在回路的话就会出现死循环(执行A的前提是执行B,执行B的前提是执行c,执行C的前提是执行A,这样就出现了死循环)

    1.AOV网中没有回路 --->AOV网为有向无环图

    1.选择顶点的顺序不同,就能够得到不同的拓扑序列,所以一个图的拓扑序列不唯一

    1.当我们按照上面的方法来构造拓扑有序序列的时候,我们会发现处于环结构中的顶点是无法进行输出到拓扑有序序列中的 --- 因为当我们想要输出环中的一个顶点的时候我们就必须保证它没有前驱,所以我们要先输出它的前驱,而要输出它的前驱就要先输出它的前驱的前驱。

    就这样沿着环走,最终我们得到的结论是如果我们要输出环中的一个顶点到拓扑有序序列中,我们需要先输出这个顶点本身,这是一个矛盾推理,所以我们无法将环中的顶点输出到拓扑有序序列中

    所以如果图的所有顶点都处于拓扑有序序列中的话,则这个图是无环图(有环的话就不能保证所有顶点都在拓扑有序序列中了)


    第四部分 --- 关键路径

    1.AOE网中的顶点既可以表示它的上一个活动已经完成了,也可以表示它的下一个活动准备开始了

    2.AOE网中的弧表示活动,而弧的权值则表示活动的持续时间

    1.汇点又称为收点

    1.关键路径就是从源点到汇点路径长度最长的路径

    2.完成整项工程所需的最少时间就是关键路径的长度,影响工程进度关系的活动就是关键路径上的边所对应的活动

    (这个证明很简单,工程结束的标志就是所有的活动都被执行,那么执行完工程的最短时间就是执行完所有活动的最短时间,而我们执行活动所需的最短时间就是图中的任意事件一结束就马上开始执行与它连接的活动,此时我们会发现,有的路径执行的快,有的路径执行的慢,而工程必须在所有活动都结束的时候才结束,所以此时我们必须等待执行慢的路径也执行到汇点事件后,整个工程才能结束,此时工程花费的时间就是最短时间 == 图中路径长度最长的路径(花费的时间最多))

    (上面这四个描述量都是建立在工程结束的时间是最短时间的前提下的)

    1.一个工程上的事件(对应顶点)的开始标志是是指向这个事件的所有活动都结束了

    2.一个工程的开始标志是源点事件开始执行,结束标志是汇点事件开始执行

    3.与同一个事件连接,且在同一边的活动可以同时执行,也可以不同时执行

    4.关键活动是关键路径上的活动,它的特点是时间余量等于0

    求关键路径方式是:通过时间余量为0这个特点,找到图中所有关键活动(边)。由这些关键活动(边)组成的路径就是图的关键路径

    关于关键活动时间余量为0的性质的证明:

    首先时间余量是什么? --- 时间余量是活动在不影响总的工程时间的情况下的开始时间的变化范围

    假设在目前工程执行的总时间 T 是最短时间T1的前提下(最短时间是在关键路径上的一个活动结束后马上执行下一个活动的状态下获得的),关键路径上的任意一个关键活动A具有时间余量,也就是说我们让A在其最早开始时间(也就是上一个活动结束后马上开始执行下一个活动)或者最晚开始时间(上一个活动结束后,等待一段时间(时间余量)再执行)执行都不会影响总的工程时间 T,显然 T > T1 ,违背我们的前提,所以假设不成立

    所以,当处于目前工程执行的总时间 T 是最短时间T1的前提下时,关键路径上的关键活动没有时间余量的

    注意上面这些推论都是建立在当前工程执行所需时间为最短时间的前提下的

    1.任意一个活动的时间余量等于这个活动的最晚开始时间 减去 这个活动的最早开始时间

    2.一个活动的最早开始时间就是在它的左事件在最早开始时间执行时,它也在这个时间开始执行

    3.一个活动的最晚开始时间就是在它的右事件在最晚开始时间执行时,它恰好在这个时间结束执行

    4.如果一个事件是最晚开始执行的话,即跟这个事件连接的

    5.选择左事件的开始时间的时候,我们必须保证右事件能够执行(我们是在这个前提下选择事件的最早开始时间和最晚开始时间)

    6.一个事件能够执行的前提是以这个事件为弧尾的弦对应的活动都执行完毕

     

     

    1.Ve是最早发生时间,Vl是最晚发生时间

    2.在工程执行时间为最短时间的前提下,源点和汇点的最早发生时间等于最晚发生时间,然后汇点的最早发生时间规定是0

     

  • 相关阅读:
    【三人一机】
    C语言刷题系列——1.将三个整数按从大到小输出
    暑假在富士康打工 50 天后,我决定奋发图强
    单调队列优化的DP——最大子序和
    小型ATC显示系统mini ATC Display
    Elasticsearch:使用 Amazon Bedrock 的 semantic_text
    ConcurrentHashMap(1.7) 相关整理
    JDK1.8下载、安装和环境配置教程
    scrapy基本使用
    编译原理:编译原理简明教程知识点梳理(应对考试版)
  • 原文地址:https://blog.csdn.net/qq_51947882/article/details/127020804