Acwinghttps://www.acwing.com/problem/content/851/
dijkatra存储无向图——邻接矩阵
分析: 此题点的数量为500,
一般情况下, 点数 < 1000 可以用邻接矩阵存储,
当点数 > 10000 用邻接表存储
1. 准备阶段:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 510; // N 开的比点数n 多10, 防止数组越界
int g[N][N]; // 用邻接矩阵存储图
int d[N]; // 表示距离
bool st[N]; // 状态数组, 遍历过得点置为true
int n, m; // 点数n, 边数m
2. 核心:
int dijkstra()
{
d[1] = 0; // 起点到起点的距离为0
//int t = -1;不能放在这
//for(int i = 0; i < n; i ++ ) 这样写也对
for(int i = 1; i <= n; i ++ )// 这里只是n次循环, 因为有n个点
{
int t = -1;// 放在内层循环,每次i+1 时 t始终等于 -1;
//如果每次不重置t, t = j 后可能不满足(t == -1 || d[t] > d[j])中的
// 任何一个 就无法遍历所有的点了
// 找到一个离原点最近的点从这开始更新其他点到原点的距离
for(int j = 1; j <= n; j ++ )
{
// j 点没有被遍历过,且 t == -1 直接把 t = j;
// j 点没有被遍历过,且 d[t] > d[j] 把 t = j;
// if(!st[j] && (t == -1 || d[t] > d[j])) t = j;
if(st[j] == false && (t == -1 || d[t] > d[j])) t = j;
}
st[t] = true; // 这个点被找过了
// 用这个点更新所有点(包括1号点)到原点的距离, 即以这个点为中间点
// 比较 是直接从j号点直接到原点近 还是 j号点先到t号点,再从t号点到原点近
for(int j = 1; j <= n; j ++ )
{
if(d[j] > d[t] + g[t][j])
d[j] = min(d[j], d[t] + g[t][j]);
}
}
// 最后一个点的距离没被更新,说明到不了最后一个点
if(d[n] == 0x3f3f3f3f ) return -1;
return d[n];
}
3. 输入输出阶段
int main()
{
cin >> n >> m;
memset(g, 0x3f, sizeof g); // 开始时, 还没有存储图,所以点的距离初始化为0x3f
memset(d, 0x3f, sizeof d); // 距离数组也是初始化为0x3f
while(m -- )// m条边, 所以有m次读入
{
int a, b, c; // a b 是指哪两个点, c 是a b两点间的距离
cin >> a >> b >> c; // 读入
g[a][b] = min(g[a][b], c); // 这里是有向图 所以是g[a][b] = min(g[a][b], c);
// 如果是无向图 g[a][b] = g[b][a] = min(g[a][b], c);
// 取出 原来a b两点间的距离g[a][b] 与 c 的最小值
}
cout << dijkstra() << endl;
return 0;
}
AC代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 510; // N 开的比点数n 多10, 防止数组越界
int g[N][N]; // 用邻接矩阵存储图
int d[N]; // 表示距离
bool st[N]; // 状态数组, 遍历过得点置为true
int n, m; // 点数n, 边数m
int dijkstra()
{
d[1] = 0; // 起点到起点的距离为0
//int t = -1;不能放在这
//for(int i = 0; i < n; i ++ ) 这样写也对
for(int i = 1; i <= n; i ++ )// 这里只是n次循环, 因为有n个点
{
int t = -1;// 放在内层循环,每次i+1 时 t始终等于 -1;
//如果每次不重置t, t = j 后可能不满足(t == -1 || d[t] > d[j])中的
// 任何一个 就无法遍历所有的点了
// 找到一个离原点最近的点从这开始更新其他点到原点的距离
for(int j = 1; j <= n; j ++ )
{
// j 点没有被遍历过,且 t == -1 直接把 t = j;
// j 点没有被遍历过,且 d[t] > d[j] 把 t = j;
// if(!st[j] && (t == -1 || d[t] > d[j])) t = j;
if(st[j] == false && (t == -1 || d[t] > d[j])) t = j;
}
st[t] = true; // 这个点被找过了
// 用这个点更新所有点(包括1号点)到原点的距离, 即以这个点为中间点
// 比较 是直接从j号点直接到原点近 还是 j号点先到t号点,再从t号点到原点近
for(int j = 1; j <= n; j ++ )
{
if(d[j] > d[t] + g[t][j])
d[j] = min(d[j], d[t] + g[t][j]);
}
}
// 最后一个点的距离没被更新,说明到不了最后一个点
if(d[n] == 0x3f3f3f3f ) return -1;
return d[n];
}
int main()
{
cin >> n >> m;
memset(g, 0x3f, sizeof g); // 开始时, 还没有存储图,所以点的距离初始化为0x3f
memset(d, 0x3f, sizeof d); // 距离数组也是初始化为0x3f
while(m -- )// m条边, 所以有m次读入
{
int a, b, c; // a b 是指哪两个点, c 是a b两点间的距离
cin >> a >> b >> c; // 读入
g[a][b] = min(g[a][b], c); // 这里是有向图 所以是g[a][b] = min(g[a][b], c);
// 如果是无向图 g[a][b] = g[b][a] = min(g[a][b], c);
// 取出 原来a b两点间的距离g[a][b] 与 c 的最小值
}
cout << dijkstra() << endl;
return 0;
}