图的基本概念
图:
- 由点(
node,或者vertex)和连接点的边(edge)组成。 - 图是点和边构成的网。
树: - 特殊的图
- 树,即连通无环图树的结点从根开始,层层扩展子树,是一种层次关系,这种层次关系,保证了树上不会出现环路。
- 两点之间的路径:有且仅有一条路径。
- 最近公共祖先。
图应用背景
- 地图:路口、道路、过路费
- 计算机网络:路由协议
- 人际关系:六度空间理论
图的种类
- 无向无权图,边没有权值、没有方向;
- 有向无权图,边有方向、无权值;
- 加权无向图,边有权值,但没有方向;
- 加权有向图;
- 有向无环图(Directed Acyclic Graph,DAG)。
图算法的时间分析
图算法的复杂度和边的数量 E、点的数量 V 相关。
O(V+E):几乎是图问题中能达到的最好程度。
O(VlogE)、O(ElogV):很好的算法。
O(V2)、O(E2)或更高:不算是好的算法。
图的存储
能快速访问:图的存储,能让程序很快定位结点 u 和 v 的边(u, v) 。
- 数组存边:简单、空间使用最少;无法快递定位
- 邻接矩阵:简单、空间使用最大;定位最快
dis[a][b] - 邻接表:空间很少,定位较快
- 链式前向星:空间更少,定位较快
注: 存储方式跟题目相匹配,占用空间少定位快也不一定是问题的最优存储方式。
数组存边
优点:简单、最省空间。
缺点:无法定位某条边。
应用:bellman-ford 算法、最小生成树的 kruskal 算法
struct Edge
{
int from, to, dis; //from起始点,to终止点,dis权值
}e[M]; //结构体数组存边
cin >> n >> m;
for(int i = 1; i <= m; ++ i)
cin >> e[i].from >> e[i].to >> e[i].dis;
邻接矩阵
二维数组: graph[NUM][NUM]
无向图: graph[i][j] = graph[j][i]
有向图: graph[i][j] != graph[j][i]
权值: graph[i][j]存结点i到j的边的权值。 例如 graph[1][2]=3,graph[2][1]=5等等。 用 graph[i][j]=INF表示i,j之间无边。
优点:
- 适合稠密图;
- 编码非常简短;
- 对边的存储、查询、更新等操作又快又简单。
缺点:
- 存储复杂度 O(V^2)太高。V=10000 时,空间 100M。
- 不能存储重边。
邻接表和链式前向星
邻接表(指针或数组下标)和链式前向星(容器模拟)的思路一样,只是表达方式不同。
应用场景:大稀疏图
优点:
- 存储效率非常高,存储复杂度O(V+E)
- 能存储重边

struct edge{
int from, to; long long w; //起点,终点,权值。起点from并没有用到,e[i]的i就是from
edge(int a, int b,long long c){
from=a; to=b; w=c;}
};
vector<edge>e[N]; //用于存储图
最短路问题
最广为人知的图论问题就是最短路径问题。
简单图的最短路径
- 树上的路径:任意 2 点之间只有一条路径
- 所有边长都为 1 的图:用
BFS搜最短路径,复杂度 O(n+m)
普通图的最短路径 - 边长:不一定等于 1,而且可能为负数
- 算法:
Floyd、Dijkstra、SPFA等,各有应用场景,不可互相替代
最短路算法比较
| 问题 | 边权 | 算法 | 时间复杂度 |
|---|---|---|---|
| 一个起点,一个终点 | 非负数; 无边权(或边权为 1) | Astar(K短路)/ 普通 | <O((m+n)logn) |
| 双向广搜 | <O((m+n)logn) | ||
| 贪心最优搜索 | <O(m+n) | ||
| 一个起点到其他所有点 | 无边权(或边权为 1) | BFS | O(m+n) |
| 非负数 | Dijkstra(堆优化 优先队列) | O((m+n)logn) | |
| 允许有负数 | SPFA | <O(mn) | |
| 所有点对之间 | 允许有负数 | Floyd-Warshall | O(n^3) |
什么算法也不能解决存在负环图的最短路的问题!最多是判断是否存在,或者找到负环。
网站推荐:CSAcademy Graph Editor

方便图论的学习。
Floyd 算法
- 最简单的最短路径算法,代码仅有 4 行
- 存图:最简单的矩阵存图
- 易懂,比暴力的搜索更简单易懂。
- 效率不高,不能用于大图
- 在某些场景下有自己的优势,难以替代。能做传递闭包问题(离散数学)
for(int k = 1; k <= n; k ++) //floyd的三重循环
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n;<

本文介绍了图的基本概念、存储方式,以及最短路问题的相关算法。图由点和边构成,存储方式有数组存边、邻接矩阵、邻接表和链式前向星等。最短路算法包括Floyd和Dijkstra,前者基于动态规划,能求所有点对间最短路径;后者基于贪心思想,处理无负权边图的单源最短路径问题。
最低0.47元/天 解锁文章
539

被折叠的 条评论
为什么被折叠?



