理论: 图论(1): 基础概念
2015-12-24 21:33
197 查看
什么是图
如上图:
说白了图(graph)就是有点(顶点:vertex)和线段(边:edge)组成;
在如上的示意图中我么用圆或者点来表示顶点, 用线段来表示边
其中特别的顶点所构成的边的集合是V, 边所构成的集合是E。
由上定义我们不难得到G = (V, E);
其中链接两个顶点 u 和v 的无向边(下面讲)用 e = (u, v)表示, 有向边用 e =
什么是有向图 / 无向图
如上文的例子就是典型的无向图, 每一条边都仅仅表示连通, 在连通的时候没有方向之分;如上图的就是有向图, 每一条边都是有指向的, 他表示从一点到另一点的单向连通, 我们常见的流程图就是一种典型的有向图;
有权图
在图中我们可以给边赋予各种各样的属性,其中比较有代表性的就是权值。边上带有权值的就是有权图。在不同的实际问题中, 权值可以代表不同的实际属性:距离、时间、花费……
无向图的术语
两个顶点之间如果有边连接, 我们就视为两个顶点相邻。 相邻顶点的序列称为路径。其中顶点和终点相同的路径称之为圈。
如果任意两点之间都能到达, 我们称这个图为连通图。
特别的我们将没有圈的连通图称之为树, 没有圈的非连通图称之为森林 为此有一个定理
一棵树的边数等于顶点数-1, 边数等于顶点数-1的图是一棵树
某个顶点连接的边数称之为这个顶点的度。
有向图的术语
在有向图中顶点v为起点的边的集合记作出度, 以顶点v 为终点的集合叫做v的出度没有圈的有向图叫做DAG 例如让我们用顶点表示整数, n 能整除 m 时从 n 向 m 连一条边, 这就构成了一个DAG‘
稀疏图 稠密图
这是一个相对的概念没有什么明确的界定一般上认为 当e > v log v 的时候这个图就是稠密图
·
·
·
·
·
·
图的存储
为了程序能对图进行处理, 需要把顶点和边用具体的用特定的数据结构存储下来。在图的表示方法中比较有代表性的就是邻接矩阵和邻接链表。需要注意的是邻接矩阵多数用于稠密图, 邻接链表用于稀疏图。
注意使用不同的储存方式可能会影响算法的时间复杂度。
接下来记顶点和边的集合为V和E V和E代表顶点和边的个数。 另外在V中, 顶点的编号是0 · v- 1
邻接矩阵
邻接矩阵使用V * V 的大小来二维数组来表示, d[i][j]表示顶点 i 和 j 的关系。由于在无向图中只需要知道“顶点i 和 j之间是否连着 以及连接的长度”这样的信息。所以我们进行如下处理
如果ij之间相互连接 且边的长度为 10:
d[i][j] = d[j][i] = 10;
而对于没有连接的图来说我们可以将其初始为+∞(0xfffffff);
最后上代码
邻接链表
在稀疏图的情况下, 使用邻接矩阵会造成极大了内存浪费;而如果用动态数组来表示“顶点2出发 到3 4 5 的边” 这样一个图的最终存储大小将减小到 0(|v|+ |e|)
事实上, 因为每个人的风格不同我们可以用不同的方式来实现邻接链表的写法
如下面的vector版
图的存储的邻接矩阵 和 邻接链表的实现
邻接矩阵#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<vector> using namespace std; const int maxn = 105; int main(void) { int V, E, map[maxn][maxn]; int a, b, len; scanf("%d %d", &V, &E); for (int i = 1; i <= V; i++) { scanf("%d %d %d", &a, &b, &len); map[a][b] = len; //map[b][a] = len; 如果是无向图则需要这句 } }
邻接链表
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int maxn = 105; struct node{ int v; int len; node(int v = 0, int len = 0) :v(v), len(len){} friend bool operator <(const node&a, const node&b) { return a.len < b.len } }; vector<node>G[maxn]; int main(void) { int a, b, len; int V, E; scanf("%d %d", &V, &E); for (int i = 1; i < V; i++) { scanf("%d %d %d", &a, &b, &len); G[a].push_back(node(b, len)); G[b].push_back(node(a, len));// 有向图不需要这句 } }
相关文章推荐
- 实战c++中的vector系列--再谈vector的insert()方法(都是make_move_iterator惹的祸)
- 实战c++中的vector系列--再谈vector的insert()方法(都是make_move_iterator惹的祸)
- JavaScript:理解worker事件api
- Codeforces Round #336 (Div. 2)
- js里cookie操作
- Codeforces 607A dp
- Halcon视频学习2.1-- 图形变量
- servlet(一)
- 从 Program Manager 看 Leader 是什么角色
- 贪吃蛇1.0&&贪吃蛇2.0
- rpm包管理功能全解
- Android之Application简介
- MATLAB 可以做什么有趣的事
- 笔试面试题总结(四)--- 软件开发
- gcc/g++ 参数详解
- Android Activity页面加载时间性能分析,以及改进要点
- Extra约会大作战 浙江工商大学2015年新生赛
- MySQL和Sql Server的sql语句区别
- Oracle开发环境搭建
- matlab字符处理