这篇文章利用图解的方式讲得十分清楚,可惜他的代码太乱了,看不懂,自己写了一份简单的。
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
const int N=1e3+5;
int ma[N][N],vis[N];
struct node{
int value;
string path;
}dis[N];
int n,m;
void dijkstra()
{
int i,j;
for(i = 1;i <= n-1; i++){
int mint = INF;
int min_design;
//寻找这一层权值最小的点
for(j = 1;j <= n; j++){
if(vis[j] == 0 && dis[j].value < mint){
mint = dis[j].value;
min_design = j;
}
}
vis[min_design] = 1;
for(j = 1;j <= n; j++){
//对于每个可以到达的j
if(ma[i][j] < INF){
//如果可以找到更小的到j点的方法,那就更新
if(dis[j].value > dis[i].value+ma[i][j]){
dis[j].value = dis[i].value + ma[i][j];
dis[j].path = dis[j].path + "-->v"+to_string((i+1));
}
}
}
}
}
void path(int begin);
int main()
{
scanf("%d%d",&n,&m);
int i,j;
for(i = 1;i <= n; i++){//初始化
for(j = 1;j <=n; j++){
if(i == j) ma[i][j] = 0;
else ma[i][j] = INF;
}
}
for(i = 1;i <= m; i++){
int x1,x2,y;
scanf("%d%d%d",&x1,&x2,&y);
ma[x1][x2] = y;
ma[x2][x1] = y;
}
for(i = 1;i <= n; i++){
dis[i].value = ma[1][i];//从点1可以达到的点,存入dis
dis[i].path = "v" + to_string(1) + "-->" +to_string(i+1);
}
vis[1] = 1;
dijkstra();
for(i = 1;i <= n; i++){
cout<<dis[i].value<<" ";
}cout<<"\n";
path(1);
return 0;
}
void path(int begin)
{
string str;
str = "v"+ to_string(begin);
printf("以%s为起点的图的最短路径为:",str.c_str());
for(int i = 0;i != n;i++){
if(dis[i].value != INF){
cout<< dis[i].path << "=" << dis[i].value <<"\n";
}else{
cout<< dis[i].path <<"是无最短路径的"<<"\n";
}
}
}
/*
6 8
1 3 10
1 5 30
1 6 100
2 3 5
3 4 50
4 6 10
5 6 60
5 4 20
*/
Decv++ 不支持c++11标准,所以用to_string时需要在编译器加入如上指令;
加强例题:紧急救援
#include<bits/stdc++.h>
using namespace std;
#define INF 1e9+7
const int N = 1005;
int ma[N][N];
int army[N];//每个城市的军队
int added[N];//标志该点是否已经加入了最短路径集合
int distanced[N];//用于记录到当前点的长度
int path[N];//用于保存最短路径,前驱
int pathNum[N];//统计到当前点有多少种不同的路径
int armyNum[N];//统计到当前点已经集合了多少军队
int n,m,s,d;
void initial();
void dijkstra();
int main()
{
cin>>n>>m>>s>>d;
int i,j;
initial();
dijkstra();
printf("%d %d\n",pathNum[d],armyNum[d]);
i = d;
int p[N];
int count = 0;
while(i != s){
p[count++] = i;
i = path[i];
}
for(i = count;i >= 0; i--){
if(i == count){
printf("%d",s);
}else{
printf(" %d",p[i]);
}
}
printf("\n");
}
void initial()
{
int i,j;
for(i = 0;i < n; i++) cin>>army[i];
for(i = 0;i < n; i++){
for(j = 0;j < n; j++){
ma[i][j] = INF;
}
}
for(i = 0;i < m; i++){
int x,y,len;
cin>>x>>y>>len;
ma[x][y] = ma[y][x] = len;
}
}
void dijkstra()
{
int i,j;
for(i = 0;i < n; i++){//初始化所有;
added[i] = 0;
path[i] = s;
distanced[i] = ma[s][i];//s点到i点
pathNum[i] = 1;
armyNum[i] = army[s] + army[i];
}
//取出第一个点
added[s] = 1;
distanced[s] = 0;
path[s] = s;
pathNum[s] = 1;
armyNum[s] = army[s];
//循环讲其余n-1个点一次选取从s到v路径最短的那个点加入到
//是最短路径的集合种,并更新对应的状态
for(i = 1;i <=n-1 ; i++){
int min_distanced = INF;
int v;//前驱
for(j = 0;j < n; j++){
if(added[j] == 0 && min_distanced>distanced[j]){
v = j;
min_distanced = distanced[j];
}
}
added[v] = 1;//找到最小的
for(j = 0;j < n; j++){
if(added[j] != 0) continue;
if(distanced[j] > distanced[v] + ma[v][j]){
distanced[j] = distanced[v] +ma[v][j];
path[j] = v;//路径添加
pathNum[j] = pathNum[v];
armyNum[j] = armyNum[v] + army[j];
}
else if(distanced[j] == distanced[v]+ma[v][j]){
pathNum[j] += pathNum[v];
//路径长度相等情况比军队数量
if(armyNum[j] < armyNum[v]+army[j]){
armyNum[j] = armyNum[v] + army[j];
path[j] = v;
}
}
}
}
}