练习4——图论总结

来源:互联网 发布:液压自动车床编程 编辑:程序博客网 时间:2024/06/06 03:30

在最后一个专题,我们学习了图论,了解了什么是图,一些常见的图,以及一些图算法。

图的概念

图是由顶点集合以及顶点间的关系的集合组成的一种关系的数学表示。

几种常见的图

  • 有向图:图中的边是有方向的。E (x ,y) 和E ( y ,x)表示的边不同。
  • 无向图:图中的边是没有方向的。
  • 完全图(暂时还没有接触过):n个顶点的图两两连边,即有 n(n-1)/2条边。

图的表示

  • 邻接矩阵(Adjacency Matrix)法,设图G=(V,E)是一个有N个顶点的图,图的邻接矩阵是一个二维数组G.edge[N][N],[i][j]表示的就是两个顶点之间的关系,没关系用0表示,反之用权值表示。

  • 邻接表(Adjacency List)法,同一个顶点发出的边链接在同一个边链表中,每一个链结点代表一条边,结点中另一个顶点的下表dest和指针link

常见的算法

并查集(以ProblemC等为代表)

将编号分别为1…N的N个对象划分为不相交集合,在每个集合中,选择其中某个元素代表所在集合。
常见两种操作:

  • 合并两个集合
merge(a, b){    if (a<b)       set[b] = a;    else       set[a] = b;}
  • 查找某元素属于哪个集合
int find(int x){    if(x!=father[x])        father[x]=find(father[x]);    return father[x];}

最小生成树(以ProblemA,ProblemD为代表)

最小生成树问题,按照我的理解,就是用最低的权值和,来让一个不连通的图连通。
由于Prim算法我还没怎么掌握,那我在这里说一下kruskal算法。

  • 对所有边从小到大排序;
  • 依次试探将边和它的端点加入生成树,如果加入此边后不产生圈,则将边和它的端点加入生成树;
  • 否则,将它删去;直到生成树中有了n-1条边,即告终止。

    这种算法非常容易理解,而且做题的时候有固定的套路,一般我会写一个kruskal()函数,对于不同的题只要修改一下main()函数中输出输出的内容,就可以的出正确的结论了。并且kruskal算法和并查集的联系非常紧密,find()函数和merge()函数基本这类问题都会用到。

单源最短路径算法(以ProblemI为代表)

最短路径问题,按照我的理解,就是对于这个图来说,求出起始点到其他任意点的权值和的最小值。
这个系列我只懂Dijkstra一个算法,也是比较简单的一个算法,它有点类似于Prim算法。它的基本思想是这样的。

设置一个集合S存放已经找到最短路径的顶点,S的初始状态只包含源点v,对vi∈V-S,假设从源点v到vi的有向边为最短路径。以后每求得一条最短路径v, …, vk,就将vk加入集合S中,并将路径v, …, vk , vi与原来的假设相比较,取路径长度较小者为最短路径。重复上述过程,直到集合V中全部顶点加入到集合S中。

解决这个问题的数据结构是,数组dist[n],dist[i]表示当前所找到的从始点v到终点vi的最短路径的长度。数组path[n],表示当前所找到的从始点v到终点vi的最短路径。数组s[n].存放源点和已经生成的终点,其初态为只有一个源点v。

感想

图论,是ACM程序设计这门课的最后一个专题,我觉得也是最难的一个专题,上述所提及的算法,只是图论中算法的极小一部分,图论的综合性比较强,比如有的图论题甚至会用到贪心或搜索的思想,所以遇到具体的问题应该具体的对待。
图论题的另一个特点是模板性非常强,对于常用的算法,只要将其编写成函数,遇到同类问题,只要将现成的函数复制进去,并且修改一下mian()函数和输入输出格式,就可以正确的得出结论。
我觉得,图论的知识在以后的工作中应用性比较强,例如在道路修建,铁路调度,电子地图制作,打车软件等领域,图论的部分思想渗透其中,所以说,学好图论很重要!

0 0
原创粉丝点击