Dijkstra算法:
使用Dijkstra算法有前提条件,所有的边为正。
讲这个算法之前首先要先定义一个无穷大的量,用INF表示,而无穷大究竟是多大呢?我们知道在实际编程中,并不存在无穷大这个定义,每种数据类型都有其表示范围,而我们这里定义的无穷大,实际上是很大的整数,这个整数并不会影响到题目的其他数据。例如,题目中给定的数据为最大不超过100,而100000这个数相对于100已经很大了那么我们就可以定义无穷大INF = 100000。
定义一个dis数组,dis[i]表示i点到源点的最短距离。
定义一个used数组,用来标记点是否使用过。
算法思想:
初始化所有节点之间没有边,我们用无穷大来表示没有边。初始化dis数组为无穷大。初始化dis[star] = 0。
循环n次
{
在所有未被标记的节点中找到dis值最小的节点x
标记x节点
从x节点出发,更新所有边(x,y),更新dis[y] = min{dis[y], d[x] + map[x][y]}
}
例如,求0到5的最短距离:
初始化:
i |
0 |
1 |
2 |
3 |
4 |
5 |
dis |
0 |
INF |
INF |
INF |
INF |
INF |
used |
false |
false |
false |
false |
false |
false |
进行第一次的循环,找到了dis值最小的0节点,标记0节点,通过0节点去更新所有和0相关的节点得到:
i |
0 |
1 |
2 |
3 |
4 |
5 |
dis |
0 |
1 |
2 |
3 |
INF |
10 |
used |
true |
false |
false |
false |
false |
false |
进行第二次循环找到dis值最小的节点1,标记,通过1节点更新所有和1相关的节点得到:
i |
0 |
1 |
2 |
3 |
4 |
5 |
dis |
0 |
1 |
2 |
3 |
INF |
10 |
used |
true |
true |
false |
false |
false |
false |
如此类推:
第三次循环:
i |
0 |
1 |
2 |
3 |
4 |
5 |
dis |
0 |
1 |
2 |
3 |
INF |
10 |
used |
true |
true |
true |
false |
false |
false |
第四次循环:
dis[5] = min{dis[5], d[3] + map[3][5]}
i |
0 |
1 |
2 |
3 |
4 |
5 |
dis |
0 |
1 |
2 |
3 |
INF |
4 |
used |
true |
true |
true |
true |
false |
false |
第五次循环:
i |
0 |
1 |
2 |
3 |
4 |
5 |
dis |
0 |
1 |
2 |
3 |
INF |
4 |
used |
True |
true |
true |
true |
false |
true |
第六次循环:
找不到了
结束循环,输出dis[5],即0到5点的最小距离为4。
1874-畅通工程续
实现代码:
#include <iostream> using namespace std; const int MAXN = 200 + 10; int map[MAXN][MAXN]; int dis[MAXN]; //保存所有点到起点的最小距离 bool used[MAXN]; const INF = 0x3ffffff; void init(int n) { for (int i = 0; i < n; i++) { dis[i] = INF; for (int j = 0; j < n; j++) { map[i][j] = INF; } } memset (used,false,sizeof(used)); } int dijkstra(int star, int end, int n) { int MinNode; //保存最小的距离 dis[star] = 0; for (int i = 0; i < n; i++) //贪心n次 { int Min = INF; for (int j = 0; j < n; j++) { if (!used[j] && dis[j] < Min) { Min = dis[j]; MinNode = j; } } used[MinNode] = true; //把MinNode作为中间点,进行松弛操作 for (int k = 0; k < n; k++) { if (!used[k] && dis[k] > dis[MinNode] + map[MinNode][k]) { dis[k] = dis[MinNode] + map[MinNode][k]; } } } if (!used[end]) { return -1; } else { return dis[end]; } } int main() { int n,m; while(cin>>n>>m) { int a,b,c; init(n); for (int i = 0; i < m; i++) { cin>>a>>b>>c; if(c < map[a][b]) //考虑如果有重边,用最小的进行构造图(好坑爹啊!!) { map[a][b] = c; map[b][a] = c; } } int s,t; cin>>s>>t; cout<<dijkstra(s, t, n)<<endl; } return 0; }