最短路径(案例+完整步骤说明+详细注释)
步骤:
这道题最应该注意的地方就是路径不是互通的,只能单方向行驶,这就需要多一道步骤:把原地图反过来,即map[i][j]与map[j][i]交换一下,再求i~1的距离的时候,就回到了1到i距离的问题
1~i的最短路径应该怎么求得?
首先以1为头结点:
1->2:8
1->3:8
1->4:999999(不可直达)
1->5:5
现在得到距离1 节点最近的是节点5,再把节点5作为中间点,看看能不能更新一下1到别的节点的距离:
5->3:6
5->4:2(999999>5+2,所以更新1->4:7)
此时距离1最近的点还是5,但是由于5已经被探索过了,所以现在没被探索的所有点里,距离1最近的是4,故使用4作为中间点,道理同上:
4->1:8
4->5:3
这里都比原来的1->1和1->5大,所以不更新距离
此时4也被探索过了,所以现在距离1最近的点为:2或3。
先看2为中间点:
2->3:5,这里肯定也是不更新了,因为1->3小于1->2->3
再以3为中间点:
3->5:6,不更新1->5
经过上面的步骤,现在已经得到1到各个点的最短距离了,然后翻转一下地图,即可求得各个点到1的最短距离了。
此处不做赘述,请自行理解,然后这里给出代码,里边有详细注释
#include <iostream>
using namespace std;
#define INF 100
int main(){
int map[INF][INF], rMap[INF][INF], ///地图和反向地图
dis[INF],disR[INF], ///1~i的距离,以及反向后的1~i的距离
book[INF],bookR[INF], ///记录被探索过的节点,0为未探索,1为探索过的
n, m, ///n个城市,m条单向路
t1, t2, t3, ///t1~t2距离为t3
u,uR, ///用来保存最近的节点,作为下一个节点
min,minR; ///用来保存距离最近节点的长度
cin >> n >> m;
for (int i = 1; i <= n; i++){ ///初始化地图、反向地图
for (int j = 1; j <= n; j++) {
map[i][j] = rMap[i][j] = ((i == j) ? 0 : INF*1000);
}
}
for (int i = 1; i <= m; i++){ ///输入地图,并保存到map和rMap
cin >> t1 >> t2 >> t3;
map[t1][t2] = rMap[t2][t1] = t3;
}
for (int i = 1; i <= n; ++i) { ///初始化各点与1节点的可达距离
dis[i] = map[1][i];
disR[i] = rMap[1][i];
book[i] = bookR[i] = 0; ///初始为未探索
}book[1] = bookR[1] = 1; ///从节点1开始
for (int i = 1; i <= n - 1; i++){ ///开始探索路径,最多探索到n-1个节点
min = minR = INF; ///
for (int j = 1; j <= n; j++){ ///探索距离节点1的挨着的最短节点,并暂时保存到u,长度保存到min;反向同理
if (book[j] == 0 && dis[j]<min){
min = dis[j];
u = j;
}
if (bookR[j] == 0 && disR[j]<minR){
minR = disR[j];
uR = j;
}
}
book[u] = bookR[uR] = 1; ///此时以u为节点,进行探索
for (int k = 1; k <= n; k++) ///找到被u箭头指向的结点,并更新u之后的1到k节点的距离:1~u + u~k = 1~k ;反向同理
{
if (map[u][k] < INF)
{
if (dis[k]> dis[u] + map[u][k])
dis[k] = dis[u] + map[u][k];
}
if (rMap[uR][k] < INF)
{
if (disR[k]> disR[uR] + rMap[uR][k])
disR[k] = disR[uR] + rMap[uR][k];
}
}
}
int sum=0; ///最后计算出和,输出
for (int i = 1; i <= n; i++)
sum+=disR[i]+dis[i];
cout << sum << endl;
return 0;
}
附加补充一下,要是双向通路的话,利用此法也可解决,只要更改一下地图就行了,把地图关于正对角线做一下对比,取其小再赋给双方,即min(a(i, j), a(j, i)) 再分别赋值给他们俩,然后步骤一样也可以解决。