自己对Dijstra算法的理解是:
- 首先输入保存点,边的权值(注意无向图和有向图在保存时的区别)。
- 将表示从起点st到顶点 i 的距离的d[ i ]数组的每一个值初始化为INF,令d[st] = 0。
- 遍历d[ ]数组的下标 i (即顶点 i)这个操作是通过优先队列来实现的,然后遍历以顶点 i 为起点的边,更新d[ i ]的最小值。
- 最后直接访问d[en],即可得到最短距离。
通过模板题来熟悉一下这个算法吧,最短路之HDU2544
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
#define FRE() freopen("in.txt","r",stdin)
using namespace std;
typedef long long ll;
typedef pair<int,int> P;//first是距离,second是点的编号
const int maxn = 150;
int d[maxn];//数组d[i]表示从起点s到顶点 i 的最短距离
int n,m;
struct edge
{
edge(int t,int c):to(t),cost(c){}
int to;//表示这条边的终点
int cost;//该边的权重
};
vector<edge> G[maxn];//储存以下标i为起点的边
priority_queue<P,vector<P>,greater<P> > que;//遍历d[]数组的下标,更新最小值
void init()
{
for(int i = 0; i < maxn; i++)
G[i].clear();
for(int i = 0; i < m; i++)
{
int st,en,c;
scanf("%d%d%d",&st,&en,&c);
G[st].push_back(edge(en,c));//这是个无向图注意储存的方式
G[en].push_back(edge(st,c));
}
}
int main()
{
//FRE();
while(scanf("%d%d",&n,&m) && n+m)
{
init();
for(int i = 0; i < maxn; i++)
d[i]= INF;
d[1] = 0;//起点到起点本身的距离为0
que.push(P(0, 1));
while(!que.empty())
{
P p = que.top();
que.pop();
int v = p.second;
if(d[v] < p.first) continue;
for(int i = 0; i < G[v].size(); i++)
{
edge e = G[v][i];
if(d[e.to] > d[v] + e.cost)
{
d[e.to] = d[v] + e.cost;
que.push(P(d[e.to],e.to));
}
}
}
printf("%d\n",d[n]);
}
return 0;
}
另外还有一个用二维数组的写法
#include <iostream>
#include <cstring>
#include <cstdio>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 100;
int e[maxn][maxn];
int dis[maxn],vis[maxn];
int n,m;
void init()
{
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
e[i][j] = INF;
}
}
int a,b,c;
for(int i = 0; i < m; i++)
{
scanf("%d%d%d",&a,&b,&c);
e[a][b] = c;
e[b][a] = c;
}
for(int i = 1; i <= n; i++)//算出1到各个点的距离
{
dis[i] = e[1][i];
vis[i] = 0;
}
vis[1] = 1;
}
void Dij()
{
for(int i = 1; i <= n; i++)
{
int mmin = INF;
int u;
for(int j = 1; j <= n; j++)
{
if(!vis[j] && dis[j] < mmin)
{
mmin = dis[j];
u = j;
}
}
vis[u] = 1;
for(int j = 1; j <= n; j++)
{
if(!vis[j] && dis[j] > e[u][j] + dis[u])
{
dis[j] = e[u][j] + dis[u];
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m) && (m + n))
{
init();
Dij();
printf("%d\n",dis[n]);
}
return 0;
}