我的OI心得(一)之 图论(零)

来源:互联网 发布:串口数据采集实时显示 编辑:程序博客网 时间:2024/04/16 12:42

概述

图么,就是有些点,还有些边。

点么,就是点。这里没有坐标系,点不是高中数学意义上的点。一般地,我们会给点一个编号(一般都是从1开始),来帮助我们区别每个点。点也可以有权值(但不多见),就是说他自己附带一点信息什么的。

边,就是点和点间某种神奇的关系。如果从点1拉出来一条带箭头的线指向点2,就说12间有条有向边。也有无向边,其作用效果相当于一来一回两条有向边。边一般来说都有个权值,也可以没有。

点的总和和边的总和构成一个图。

 

一般来说图在计算机中有三种存储方式。三种是什么书上有。

一,邻接矩阵。对于一个点数小于5000的图来说,竞赛环境下是能用邻接矩阵存的(一般竞赛环境给64M内存,而一个integer是两个字节,自己算算)。

二,边集数组,我觉得好难听。就是三条一维数组,

l,r,w:array[1..1000000]of integer;

就是说对于一个有向边从l[i]连到r[i],权值为w[i]。这里的i仅表示第几条边,无所谓的。

三,邻接表。邻接表不一定要链表。数组也可以。比如这样:

w,num[1..5000,1..5000]of integer;count[1..5000]of integer;

其中1<=j<=count[i]count[i]i的出度。num[i,j]存的是和i相连的第j条边的那一头的那个点的编号。W照例存权值。比较适合遍历。

对于一个点i,很多情况下我们要挨个访问他指出去的点,就是遍历。如果总点数是n,那么用邻接矩阵存的图的i的遍历需要我们把n个点全部扫一遍。而邻接表只要扫count[i]个。在稀疏图里,邻接表在时间上要占优很多。你想想,要把所有的点的指出取的点遍历一遍,耗时上邻接矩阵是O(n2)的,而邻接表是O(e)的。O(e)介于O(n)O(n2)之间。

边集数组比较个性。边乱存的时候,几乎不能拿来遍历。但是我们可以排序啊~~上个快排,按l排序,就相当于把邻接表一串串挨个首尾相连了。。。

但是你想想,空间上数组邻接表用了O(n2),邻接矩阵也是;而边集数组只有O(e)。而排序之后l就变成了1,1,2,2,2,3,4,…,n的样子,再做个数组h[i]=l中第一次出现il的数组下标(就是邻接表的表头),就能实现O(e)遍历了。而排序是O(elge)的,比链表邻接表的O(e)要差点。说来说去就是链表邻接表最好,就是难操作。。因此时间吃紧空间不吃紧就数组邻接表,两个都吃紧(NOIP中不多,但不是没有)就链表邻接表或边集数组,都不吃紧就邻接矩阵好了。估计没有时间不吃紧空间吃紧。。。

原创粉丝点击