使用Dijkstra算法求解最小总费用
目录
一、实验目的及要求
1.理解最小费用问题(Dijkstra算法)的基本概念及其在图论中的应用。
2.掌握Dijkstra算法的实现,能够解决给定的问题。
3.掌握如何使用数据结构和算法解决实际问题,提高编程能力和问题解决能力。
二、实验内容
编写程序,求解最小费用问题(Dijkstra)。问题描述:假设有N个车站(车站的编号为1到N)和N个人,首先所有人均在车站1,将这N个人分派到N个车站去,每一个分派到一个车站,这些人只能乘坐公交车,每条单向公交车连接连个车站并且有一定的费用;接着这N个人又回到车站1,求最小总花费。
测试数据:
4 6
1 2 10
2 1 60
1 3 20
3 4 10
2 4 5
4 1 50
三、实验设备与环境
1.Windows 11
2.Codeblocks
四、实验设计方案
(一)实验步骤:
1.定义图的数据结构,包括节点和边。节点表示车站和人,边表示公交车连接关系和费用。
2.初始化Dijkstra算法所需的距离数组,将所有距离初始化为无穷大,将起点(车站1)的距离初始化为0。
3.使用Dijkstra算法进行求解,从起点开始,按照距离的递增顺序遍历所有节点。
4.对于每个节点,更新其相邻节点的距离,选择最小费用路径。
5.重复步骤4,直到所有节点都被访问过或无法找到更短路径为止。
6.输出最小总花费和对应的分派方案。
(二)设计思想:
1.使用优先队列(堆)来存储待访问节点,按照距离的递增顺序访问节点,实现Dijkstra算法的关键步骤。
2.使用邻接矩阵或邻接表来表示图,方便存储节点之间的连接关系和费用。
3.在更新距离时,要注意处理边的权重(费用),确保选择最小费用路径。
4.使用动态规划的思想来逐步计算最小总花费,避免重复计算。
(三)算法描述或开发流程:
1.定义图的数据结构:使用邻接矩阵或邻接表来表示图,每个节点表示一个车站或一个人,边表示公交车连接关系和费用。
2.初始化Dijkstra算法:创建一个距离数组dist[]和一个标记数组visited[],将所有距离初始化为无穷大(如INT_MAX),将起点(车站1)的距离初始化为0。将所有节点标记为未访问(false)。
3.遍历节点:使用优先队列(堆)来存储待访问节点,按照距离的递增顺序访问节点。循环执行以下步骤,直到所有节点都被访问过或无法找到更短路径为止。
3.1 从优先队列中取出距离最小的节点u,标记为已访问(true)。
3.2 遍历节点u的所有相邻节点v(即边(u, v)):如果v未被访问过,并且通过u到达v的距离小于当前已知的距离dist[v],则更新dist[v]为通过u到达v的距离,并将v加入优先队列。
3.3 将u的所有相邻节点v标记为已访问(true)。
4.输出结果:遍历完所有节点后,dist[]数组中存储的就是从起点到各个节点的最小距离。根据问题的要求,输出最小总花费和对应的分派方案。
五、实验结果
六、附录源码
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int MAXN = 1005;
const int INF = 0x3f3f3f3f;
int n, m; // n为车站数量,m为边数
vector<pair<int, int> > edge; // 存储每条边的起点和终点以及费用
int dist[MAXN]; // 存储到达每个车站的最小费用
int vis[MAXN]; // 标记每个车站是否被访问过
void dijkstra(int start) {
memset(dist, INF, sizeof(dist));
memset(vis, 0, sizeof(vis));
dist[start] = 0;
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq;
pq.push(make_pair(0, start));
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
if (vis[u]) continue;
vis[u] = 1;
for (int i = 0; i < edge.size(); i++) {
int v = edge[i].first;
int w = edge[i].second;
if (!vis[v] && dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
pq.push(make_pair(dist[v], v)); // 这里应该使用 '>' 而非 '>>'
}
}
}
}
int main() {
cin >> n >> m;
edge.clear();
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
edge.push_back(make_pair(v, w)); // 将边加入到edge中,并按照边的终点进行排序
}
dijkstra(1); // 从车站1开始求解最小费用问题
int ans = 0;
for (int i = 2; i <= n; i++) {
ans += dist[i]; // 将每个人分派到各个车站,并累加总费用
}
cout << ans << endl; // 输出最小总花费
return 0;
}