- 47. 参加科学大会(第六期模拟笔试)
Dijkstra算法,适用于有向图、边的权值没有负数,解决一个点到其他所有点的最短路径;采用贪心策略。维护一个集合S,包含已找到最短路径的节点。每次从集合S之外的节点中,选择一个距离源点最近的节点加入S,并松弛(更新)其所有邻居的距离。
- 准备distance数组,保存源点到i点的最短距离;准备visited数组,记录节点i是否从小根堆中弹出过
- 准备小根堆,保存节点i以及源点到节点i的距离(邻接表保存i和源点到i的距离,邻接矩阵保存x,y与源点到i的距离),小根堆根据距离组织
- 默认情况:
std::less→ 大根堆 → 较大的元素在堆顶 - 比较函数返回true表示第一个参数应该排在第二个参数后面
- 默认情况:
- 设置distance[源点]为0,将(源点k, 0)加入小根堆
- 从小根堆中弹出节点(u, dis),然后:
- 如果visited[u]为true,continue。
- 如果visited[u]为false,设置visited[u]为true,然后检查u的所有边(k, weight):
- 检查是否越界(需要的话)
- 检查visited[k]== false且distance[u] + weight < distance[k],则更新distance[k]=distance[u] + weight,并将(k, distance[k])加入小根堆
- 处理u的所有边后,重复步骤4
- 小根堆为空,流程结束,distance表记录了源点到其他点的最短距离
#include <climits>
#include <iostream>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
class Comparer
{
public:
bool operator()(vector<int> a, vector<int> b){
return a[1] > b[1];
}
};
int main() {
int n = 0, m = 0;
cin >> n >> m;
vector<vector<int>> edges(n + 1, vector<int>(n + 1, INT_MAX));
int from, to, weight;
for (int j = 0; j < m; j++) {
cin >> from >> to >> weight;
edges[from][to] = weight;
}
int start = 1;
int end = n;
vector<int> distance(n + 1, INT_MAX);
vector<bool> visited(n + 1);
priority_queue<vector<int>,vector<vector<int>>,Comparer> pq;
pq.push({start, 0});
distance[start] = 0;
while(!pq.empty()){
vector<int> info = pq.top();
pq.pop();
int curr = info[0];
if(visited[curr]) continue;
//标记已访问
visited[curr] = true;
//更新从开始节点到其他节点的距离
for (int j = 1; j <= n; ++j) {
//节点还没有加入路径,且从开始节点到edge[0]的长度要大于从开始节点到curr再到edge[0]的长度,那么开始节点到edge[0]的长度进行更新
if (!visited[j] && edges[curr][j] != INT_MAX &&
distance[j] > distance[curr] + edges[curr][j]) {
distance[j] = distance[curr] + edges[curr][j];
pq.push({j, distance[j]});
}
}
}
if (distance[end] == INT_MAX) {
cout << -1 << endl;
} else {
cout << distance[end] << endl;
}
return 0;
}
对所有边松弛一次 能得到 与起点 一条边相连的节点最短距离。
那对所有边松弛两次 可以得到与起点 两条边相连的节点的最短距离。
#include <climits>
#include <iostream>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<vector<int>> grid;
int from, to, price;
for (int i = 0; i < m; ++i) {
cin >> from >> to >> price;
grid.push_back({from, to, price});
}
vector<int> minDist(n + 1, INT_MAX);
minDist[1] = 0;
for (int i = 1; i < n; ++i) {
for (vector<int>& info : grid) {
int from = info[0];
int to = info[1];
int price = info[2];
if (minDist[from] != INT_MAX && minDist[to] > minDist[from] + price) {
minDist[to] = minDist[from] + price;
}
}
}
if (minDist[n] == INT_MAX) {
cout << "unconnected" << endl;
} else {
cout << minDist[n] << endl;
}
return 0;
}
```# 算法训练1-day49-图论