这里写目录标题
- 例题引入: 路径——蓝桥2021省赛
- 题目分析
- 题解
- !!!求最短路径问题!!!
- 应用场景
- 图的基础
- Floyd算法
- Acwing-843.有边数限制的最短路
- 简单的思路讲解
- Dijkstra算法
例题引入: 路径——蓝桥2021省赛
题目分析
- 求最短路径
- 求最小公倍数
题解
!!!求最短路径问题!!!
- 求最短路径—》会想到什么解题思路?
- 我最先想到的是:dfs和bfs(最短路径,这俩求解肯定没问题)
- 然后我又想到了dp(动态规划):因为有初始状态和最后一步(求两点之间的最短路径)。那我要是用dp[i]表示到i点的最短路径,有没有可能写出状态转移方程呢?
但因为我知道最短路径问题有现成的算法去解题,所以,先学一下吧。
至于dp能不能解的出来,怎么解,之后有时间我再回来研究。
应用场景
- 管道铺设,线路安装,地图规划等路径问题
- 例:
- 旅行规划:想知道任意两个城市之间的最短路径——用Floyd算法
图的基础
时间来不及,先整个大纲。之后会补充 重点先放在两个算法上
- 图的基本概念(可对应好友关系)
- 顶点:用户
- 边:俩用户是好友,那俩人之间就有一条边连着
- 度:某用户的好友数量。有向图中,还分入度(指进来的)和出度(指出去的)
- 无向图和有向图
- 无向图:没箭头的图(不关注指哪)
- 有向图:有箭头的图(关注二者间关系的)
- 无权图和有权图
(权就是指,俩人的亲密度)- 无权图:没数字的(不关注关系的亲密度)
- 有权图:有数字的(关注俩人的亲密度)
这是一个带权的有向图(图片来自:JavaGuide)
- 图的存储
存一个图最简单的方式就是——存到一个二维数组里(优点:找顶点间关系高效;缺点:费空间)
像这样(图片来自:JavaGuide)
Floyd算法
Acwing-843.有边数限制的最短路
给定一个n个点m条边的有向图,图中可能存在重边和自环,
简单的思路讲解
求任意两点间的最短路径问题(如图)
- 先来想
- 假设我们要求顶点1到顶点3间的最小路径 首先,1到3 自己就有一条权值为6的路径
- 然后,通过图 可以很明显的知道,1到3,可以通过在顶点2中转 到达,其路径值为2+3=5;
- 而5<6 这时,需要更新1到3的最短路径为5
归纳一下:
- 在找任意两点间的最短路径时,显然是不仅要找直接路径,还要找从中转点到达的路径,比较之后,才能得出两点间的最短路径
- 而中转点基本上都不止一个—》怎么有逻辑的给他表示出来呢?
- 我们来推一下
- 我们用e[n+1][n+1] 来存放这个图(因为for循环中用1~n比较好表示),其中,e[i][j] 表示i到j的最短路径
- 假设现在只允许经过顶点1中转,求任意两点(i到j)的最短路径
–》只需要判定e[i][1]+e[1][j] 是否比 e[i][j]小 即可
- 怎么写
//经过顶点1中转
//经过顶点1中转
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(e[i][j] > e[i][1]+e[1][j]){
e[i][j] = e[i][1]+e[1][j];
}
//同理,经过顶点1和顶点2中转呢?
//经过顶点1
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(e[i][j] > e[i][1] + e[1][j]){
e[i][j] = e[i][1] + e[1][j];
}
//经过顶点2
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(e[i][j] > e[i][2] + e[2][j]){
e[i][j] = e[i][2] + e[2][j];
}
//同理,经过3,4顶点也是这样
//把他们合并到一块写
for(int k=1;k<=n;k++) //依次经过1~n中的第k个点进行中转
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(e[i][j] > e[i][k] + e[k][j]){
e[i][j] = e[i][k] + e[k][j];
}