Dijkstra是用来解决图的最短路径问题的,核心思想我觉得是根据源点开始,在所有可能的路径中不断寻找最小权的路径,直到终点为止,从而形成图中两个点的最短路径。
具体的算法思路可以参考我找到的视频:
https://www.bilibili.com/video/av38254646?from=search&seid=5219412858608359008
用邻接矩阵实现的图:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
int map[110][110];//这就是map数组,存储图
int dis[10010];//dis数组,存储估计值
int book[10010];//book[i]代表这个点有没有被当做源点去搜索过,1为有,0为没有。这样就不会重复搜索了。
int n,m; //m是结点个数,n是行数,邻接矩阵行数就是列数
void dijkstra(int u)//主函数,参数是源点编号
{
memset(dis,88,sizeof(dis));//把dis数组附最大值(88不是十进制的88,其实很大)
int start=u;//先从源点搜索
book[start]=1;//标记源点已经搜索过
for(int i=0;i<n;i++)
dis[i]=min(dis[i],map[start][i]);//先更新一遍
for(int i=0;i<n-1;i++)
{
int minn=9999999;//这就是刚才所说的minn
for(int j=0;j<n;j++)
if(book[j]==0 && minn>dis[j])
{
minn=dis[j];
start=j;//找到离源点最近的点,然后把编号记录下来,用于搜索。
}
book[start]=1;
for(int j=0;j<n;j++)
dis[j]=min(dis[j],dis[start]+map[start][j]);//以新的点来更新dis。
}
}
int main()
{
cin>>n>>m;
memset(map,88,sizeof(map));
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
map[a][b]=c;
map[b][a]=c; //无向图矩阵应该是对称的
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i==j)
map[i][j]=0;
int u;
cin>>u;
dijkstra(u);//以1为源点。
for(int i=1;i<=n;i++)
cout<<dis[i]<<" ";
}
用邻接表实现的图:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
int value[10010],to[10010],next[10010];
int head[10010],total;
int book[10010];
int dis[10010];
int n,m;
void adl(int a,int b,int c)
{
total++;
to[total]=b;
value[total]=c;
next[total]=head[a];
head[a]=total;
}
void dijkstra(int u)
{
memset(dis,88,sizeof(dis));
memset(book,0,sizeof(book));
dis[u]=0;
for(int i=1;i<=n;i++)
{
int start=-1;
for(int j=1;j<=n;j++)
if(book[j]==0 && (dis[start]>dis[j] || start==-1))
start=j;
book[start]=1;
for(int e=head[start];e;e=next[e])
dis[to[e]]=min(dis[to[e]],dis[start]+value[e]);
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
adl(a,b,c);
}
dijkstra(1);
for(int i=1;i<=n;i++)
cout<<dis[i]<<" ";
}
网友评论