📅  最后修改于: 2023-12-03 15:28:47.015000             🧑  作者: Mango
本题是一道考察图论算法的题目,需要求出从某个起点S开始,遍历整个图的最短路径。
给定一个由n个节点和m条边组成的有向无环图,请你找到从S节点开始遍历整个图的最短路径。每条边都有一个权重,代表遍历这条边需要的时间,起点S节点到其他节点的距离均为正整数。
这是一个典型的单源最短路径的问题,我们可以考虑使用Dijkstra算法或者Bellman-Ford算法进行求解。
Dijkstra算法需要保证边的权重为非负数,而Bellman-Ford算法能够处理边权重为负数的情况。但是由于本题保证距离是正整数,因此我们选择使用Dijkstra算法进行求解。
Dijkstra算法的基本思想是维护一个集合S,其中的节点已经被确定了最短路径,而其余的节点还没有确定。初始状态下,S集合只有起点S。每次从集合V-S中,选择一个距离起点S最近的节点u加入集合S中,然后更新S集合中节点的距离值。
具体的,我们可以使用一个长度为n的dist数组,表示某个节点到起点S的距离,初始状态下dist[S]=0,其他节点的dist都是无穷大。每次选择最小的dist值对应的节点u,然后更新S集合中节点的距离值,即对于每个u的未访问的邻居v,如果dist[v]>dist[u]+w(u,v),则dist[v]=dist[u]+w(u,v)。
进行n次操作后,求出所有节点到起点S的最短距离,这就是结果。
实现需要用到一个优先队列,可以使用STL中的priority_queue进行实现。
代码如下:
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int INF = 1e9; // 表示无穷大
typedef pair<int, int> P; // 用于存储节点和其到起点的距离
void dijkstra(int s, vector<vector<P>>& g, vector<int>& dist)
{
dist[s] = 0;
priority_queue<P, vector<P>, greater<P>> q;
q.push(make_pair(0, s));
while(!q.empty()){
P p = q.top();
q.pop();
int v = p.second;
if(dist[v] < p.first) continue;
for(auto& it: g[v]){
int u = it.first;
int ww = it.second;
if(dist[u] > dist[v]+ww){
dist[u] = dist[v]+ww;
q.push(make_pair(dist[u], u));
}
}
}
}
int main()
{
int n, m, s;
cin >> n >> m >> s;
vector<vector<P>> g(n);
vector<int> dist(n, INF);
for(int i=0; i<m; ++i){
int u, v, w;
cin >> u >> v >> w;
g[u].push_back(make_pair(v, w));
}
dijkstra(s, g, dist);
for(int i=0; i<n; ++i){
if(dist[i]==INF) cout << "INF" << endl; // 无法到达
else cout << dist[i] << endl;
}
return 0;
}
使用Dijkstra算法,时间复杂度为O(mlogn)。其中m表示边的数量,n表示节点数量。本题中,m和n取值范围分别为1<=m,n<=10^4,因此算法的时间复杂度是可行的。