胆小了很久,感觉还是有必要作为一个菜鸡的角度把这个算法总结出来,主要原因就是因为自己总是忘记这个重要的算法,希望这次通过写博客总结可以记录下来。
经典题干:输入顶点数量,边数量,然后根据边的数量输入点到点的距离长度,最后得出从node=0到node=node_num-1的距离。
代码模板:
#include "iostream"
using namespace std;
#define MAX 999999;
#define NodeMax 1000;
int map[2000][2000];
int djs[2000] = {0};
void Djs(int node) {
bool visited[2000] = {false};
visited[0] = true;
for (int i = 1; i < node; i++) {
int min = MAX;
int tag = 0;
for (int j = 0; j < node; j++)
if (!visited[j] && min > djs[j]) {
min = djs[j];
tag = j;
}
visited[tag] = true;
for (int j = 0; j < node; j++)
if (!visited[j] && djs[j] > (djs[tag] + map[tag][j]))
djs[j] = djs[tag] + map[tag][j];
}
}
int main() {
int node, side;
cin >> node >> side;
for (int i = 0; i < node; i++) {
map[i][i] = 0;
for (int j = 0; j < i; j++) {
map[i][j] = MAX;
map[j][i] = MAX;
}
}
for (int i = 0; i < side; i++) {
int node1, node2, cost;
cin >> node1 >> node2 >> cost;
node1--;node2--;
if (cost < map[node1][node2]) {
map[node1][node2] = cost;
map[node2][node1] = cost;
}
}
for (int i = 0; i < node; i++)
djs[i] = map[i][0];
Djs(node);
cout << djs[node - 1];
return 0;
}
在这段代码中,其实最主要的是明白Djs函数部分!
前期准备:
1.初始好map信息函数,把MAX填充到map中,map矩阵的含义为记录点到点的距离信息,这个矩阵只要前期输入好后,后期算法部分是完全不会改变的;map矩阵是一个对称矩阵,对角线的元素都是0。
2.在map矩阵中输入信息,根据边side_num的多少输入距离信息;这里注意一点,会重复输入同一条的信息,所以需要进行保留最小的那条边。
3.生成djs矩阵,djs矩阵的含义是记录该点到node=0(出发点)的距离信息,在开始初始化的时候,就直接选择map[1][...]就好了。
Djs算法部分:
1.构建visit矩阵,这个矩阵用于确定,指定位置的点有没有找到最小路径(对应就是djs矩阵中的数值);初始化的时候,除了起点到起点自己的信息赋值成为true(自己到自己就是0),其他的点全部设置成为false。
2.进行node_num-1次循环。这里的每一次循环都确定了一条最短的路径(这里我也解释不是很清楚,为什么一次循环就一定确定了一条路线,但是在纸上演示的时候,确实这样,这也是算法的核心吧)。
3.在没有确定最短路径信息的点中确定djs矩阵最小值,之后以这个点tag作为出发点进行考量。
4.确定最小点后,直接确定好这个点tag就是当前确定的最小路径点(也就是把visit矩阵赋值为true)。
5.确定了这个tag点后,还需要在这个tag的角度出发,考虑这个点对其他的点的影响。更新djs矩阵的其他的点j,这个时候,就考虑是直接到j点的距离小,还是经过k点绕一下的距离小,因为现在最小点是k点;如果绕一下更小,则更新djs矩阵(同样更新的点必须是visit矩阵记录的没有访问过的点),但是不更新visit矩阵。
最后:
返回djs[node_num-1]信息即可