所谓的迪杰斯特拉算法,就是一个用来求一个图中某点到其它点的最短路径的算法。
大致方法:
遍历所有节点,找到离起点最近的一个点(那么这个点到起点的最小距离肯定是起点到这个点的这条边的权值),然后标记这个点被使用过了
以1中的那个点为中继,更新其它节点到起点的距离,也就是更新这个dis数组,怎么更新呢?当然是遍历所有点,如果这个点原先到起点的距离大于现在经过中继到起点的距离,那么就用这个较小的值更新dis数组
下面讲一下是怎么实现的。
首先是采用邻接矩阵来储存图,有向图或者无向图均可,这里用有向图举例:
const int INF=1e7;
int mp[105][105];
int n;//节点个数
int m;//边的条数
cin>>n>>m;
//初始化边为无穷大
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mp[i][j]=INF;
//输入边的数据
while(m--)
{
cin>>u>>v>>w;
mp[u][v]=min(mp[u][v],w);
//若是无向图,则增加下面一行:
//mp[v][u]=mp[u][v];
}
接下来就是迪杰斯特拉算法辣:
void Dijkstra(int u)
{
//首先是要开一个数组来储存我们的到某个点的最短距离
int dis[105];
//然后开一个数组用来记录这个点有没有被遍历
bool visit[105];
//初始化起点u到其他各个顶点的最短路径长度
for(int i=1;i<=n;i++)
{
dis[i]=mp[u][i];
visit[i]=false;
}
//起点到起点的距离当然是0咯:
dis[u]=0;
visit[u]=true;
//循环寻找离起点最近的点:
for(int i=1;i<=n;i++)
{
int min=INF;
int t=u;
for(int j=1;j<=n;j++)
if(!visit[j]&&dis[j]<min)
{
t=j;
min=dis[j];
}
if(t==u)
return;//没有与起点连接的点了,跳出循环。
visit[t]=true;
for(int j=1;j<=n;j++)//更新与中继点t邻接的点到起点u的距离
if(!visit[j]&&mp[t][j]<INF)
if(dis[j]>(dis[t]+mp[t][j]))
dis[j]=dis[t]+mp[t][j];
}
}
例题:
问题 H: 2.5 一场说走就走的旅行
内存限制:128 MB时间限制:1.000 S评测方式:文本比较命题人:admin提交:106解决:36
题目描述
有一天,孩子回来对我说:“妈妈,听说马尔代夫很不错,放假了我想去玩。”
马尔代夫?我也想去!没有人不向往一场说走就走的旅行!
“其实我想去的地方很多,呼伦贝尔大草原、玉龙雪山、布达拉宫、艾菲尔铁塔……”小孩子还说着他感兴趣的地方。
于是我们拿出地图,标出想去的地点,然后计算最短路线,估算大约所需的时间,有了这张秘制地图,一场说走就走的旅行不是梦!
“哇,感觉我们像凡尔纳的《环游地球八十天》,好激动!可是老妈你也太 out 了,学计算机的最短路线你用手算?”
暴汗……,“小子你别牛,你知道怎么算?”
“呃,好像是叫什么迪科斯彻的人会算。”
哈哈,关键时刻还要老妈上场了!
输入
样例组数:
t ( 0 < t <= 10 )
城市的个数:
n ( 0 < n < 100 )
城市之间的路线的个数:
m ( 0 < m < 10000 )
请输入城市之间的路线以及距离:
( 0 < ui, vi, di <= 100 )
u1 v1 d1
u2 v2 d2
...
ui vi di
请输入小明所在的位置:
l ( 0 < l < 100 )
输出
小明到各个城市的最短距离;
l1 l2 ... ln (若某城市无法达到则输出impossible)
样例输入 复制
1
5
11
1 5 12
5 1 8
1 2 16
2 1 29
5 2 32
2 4 13
4 2 27
1 3 15
3 1 21
3 4 7
4 3 19
5
样例输出 复制
8 24 23 30 0
#include<bits/stdc++.h>
using namespace std;
const int INF=1e7;//初始化无穷大为10000000
int mp[105][105];
int dist[105],n,m;
bool flag[105];//如果flag[i]等于true,说明顶点i已经加入到集合S;否则顶点i属于集合V-S.
void Dijkstra(int u)
{
for(int i=1;i<=n;i++)
{
dist[i]=mp[u][i];//初始化源点u到其他各个顶点的最短路径长度。
flag[i]=false;
}
dist[u]=0;
flag[u]=true;//初始时,集合s中只有一个元素:源点u。
for(int i=1;i<=n;i++)
{
int min=INF;
int t=u;
for(int j=1;j<=n;j++)//在集合V-S中寻找距离源点u最近的顶点t。
if(!flag[j]&&dist[j]<min)
{
t=j;
min=dist[j];
}
if(t==u)
return;//找不到t,跳出循环。
flag[t]=true;//否则,将t加入集合。
for(int j=1;j<=n;j++)//更新集合V-S中与t邻接的顶点到源点u的距离
if(!flag[j]&&mp[t][j]<INF)//!flag[j]表示j在V-S中
if(dist[j]>(dist[t]+mp[t][j]))
dist[j]=dist[t]+mp[t][j];
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
int u,v,w,st;
cin>>n;
cin>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mp[i][j]=INF;
while(m--)
{
cin>>u>>v>>w;
mp[u][v]=min(mp[u][v],w);
}
cin>>st;
Dijkstra(st);
for(int i=1;i<=n;i++)
{
if(dist[i]==INF)
cout<<"impossible"<<" ";
else
cout<<dist[i]<<" ";
}
cout<<endl;
}
return 0;
}