📜  门| GATE CS Mock 2018 |设置 2 |第 51 题(1)

📅  最后修改于: 2023-12-03 14:58:22.423000             🧑  作者: Mango

题目描述

本题是 Gate CS Mock 2018 的第 2 套试卷中的第 51 道题目。

给定一个有向无环图(DAG)和源顶点 S,求从 S 到其他所有顶点的最短路径的长度。请实现 Dijkstra 算法。

输入格式

输入的第一行包含一个整数 T,表示测试数据组数。

对于每组测试数据,第一行包含三个整数 N、M 和 S。分别表示图中顶点的数量、边的数量和源顶点的编号。顶点编号从 1 开始。

接下来 M 行,每行包含三个整数 u、v 和 w,表示一条从顶点 u 到顶点 v 的有向边,边的长度为 w。

输出格式

对于每组测试数据,输出 N-1 行,每行一个整数,第 i 行表示从 S 到顶点 i 的最短路径的长度。

如果从 S 到某个顶点不存在路径,则输出 -1。

样例输入
2
3 3 1
1 2 2
2 3 1
1 3 4
3 2 1
1 2 2
2 3 1
样例输出
2
3
-1
-1
程序实现

首先,我们需要使用 C++ 中的 STL 中的优先队列 priority_queue 来实现 Dijkstra 算法。

我们定义一个 pair 结构体,用来保存当前顶点到源顶点 S 的距离,以及顶点的编号:

struct Pair {
  int dist, node;
};

然后,我们定义一个 vector 数组 dist,初始化为 -1,用来保存顶点到源顶点 S 的最短距离:

vector<int> dist(n + 1, -1);

定义之后,我们将源顶点 S 到源顶点 S 的距离设为 0:

dist[S] = 0;

接下来,我们定义 STL 中的优先队列 priority_queue,用来保存所有可以到达的顶点及其到源顶点 S 的距离。在优先队列中,我们定义 greater 用来排序,将距离近的顶点先放入队列中:

priority_queue<Pair, vector<Pair>, greater<Pair>> pq;

pq.push(make_pair(0, S));

然后,我们利用 STL 中的 vector 数组 graph,将所有的边存入其中。graph[i] 表示从顶点 i 出发可以到达的下一个顶点及其距离:

vector<pair<int, int>> graph[n + 1];

for (int i = 0; i < M; ++i) {
  int u, v, w;
  cin >> u >> v >> w;
  graph[u].push_back(make_pair(v, w));
}

最后,我们就可以进行核心算法:

while (!pq.empty()) {
  int u = pq.top().second;
  pq.pop();

  for (auto v : graph[u]) {
    int newDist = dist[u] + v.second;

    if (dist[v.first] == -1 || dist[v.first] > newDist) {
      dist[v.first] = newDist;
      pq.push(make_pair(newDist, v.first));
    }
  }
}

完整代码如下:

#include <iostream>
#include <vector>
#include <queue>
#include <utility>

using namespace std;

struct Pair {
  int dist, node;
};

int main() {
  int t;
  cin >> t;

  while (t--) {
    int n, m, S;
    cin >> n >> m >> S;

    vector<int> dist(n + 1, -1);
    dist[S] = 0;

    priority_queue<Pair, vector<Pair>, greater<Pair>> pq;
    pq.push(make_pair(0, S));

    vector<pair<int, int>> graph[n + 1];

    for (int i = 0; i < m; ++i) {
      int u, v, w;
      cin >> u >> v >> w;
      graph[u].push_back(make_pair(v, w));
    }

    while (!pq.empty()) {
      int u = pq.top().second;
      pq.pop();

      for (auto v : graph[u]) {
        int newDist = dist[u] + v.second;

        if (dist[v.first] == -1 || dist[v.first] > newDist) {
          dist[v.first] = newDist;
          pq.push(make_pair(newDist, v.first));
        }
      }
    }

    for (int i = 1; i <= n; ++i) {
      if (i != S) {
        cout << dist[i] << endl;
      }
    }
  }

  return 0;
}
Markdown 代码片段
## 题目描述

本题是 Gate CS Mock 2018 的第 2 套试卷中的第 51 道题目。

给定一个有向无环图(DAG)和源顶点 S,求从 S 到其他所有顶点的最短路径的长度。请实现 Dijkstra 算法。

## 输入格式

输入的第一行包含一个整数 T,表示测试数据组数。

对于每组测试数据,第一行包含三个整数 N、M 和 S。分别表示图中顶点的数量、边的数量和源顶点的编号。顶点编号从 1 开始。

接下来 M 行,每行包含三个整数 u、v 和 w,表示一条从顶点 u 到顶点 v 的有向边,边的长度为 w。

## 输出格式

对于每组测试数据,输出 N-1 行,每行一个整数,第 i 行表示从 S 到顶点 i 的最短路径的长度。

如果从 S 到某个顶点不存在路径,则输出 -1。

## 样例输入

2 3 3 1 1 2 2 2 3 1 1 3 4 3 2 1 1 2 2 2 3 1


## 样例输出

2 3 -1 -1


## 程序实现

首先,我们需要使用 C++ 中的 STL 中的优先队列 priority_queue 来实现 Dijkstra 算法。

我们定义一个 pair 结构体,用来保存当前顶点到源顶点 S 的距离,以及顶点的编号:

struct Pair { int dist, node; };


然后,我们定义一个 vector 数组 dist,初始化为 -1,用来保存顶点到源顶点 S 的最短距离:

vector dist(n + 1, -1);


定义之后,我们将源顶点 S 到源顶点 S 的距离设为 0:

dist[S] = 0;


接下来,我们定义 STL 中的优先队列 priority_queue,用来保存所有可以到达的顶点及其到源顶点 S 的距离。在优先队列中,我们定义 greater<Pair> 用来排序,将距离近的顶点先放入队列中:

priority_queue<Pair, vector, greater> pq;

pq.push(make_pair(0, S));


然后,我们利用 STL 中的 vector 数组 graph,将所有的边存入其中。graph[i] 表示从顶点 i 出发可以到达的下一个顶点及其距离:

vector<pair<int, int>> graph[n + 1];

for (int i = 0; i < M; ++i) { int u, v, w; cin >> u >> v >> w; graph[u].push_back(make_pair(v, w)); }


最后,我们就可以进行核心算法:

while (!pq.empty()) { int u = pq.top().second; pq.pop();

for (auto v : graph[u]) { int newDist = dist[u] + v.second;

if (dist[v.first] == -1 || dist[v.first] > newDist) {
  dist[v.first] = newDist;
  pq.push(make_pair(newDist, v.first));
}

} }


完整代码如下:

#include #include #include #include

using namespace std;

struct Pair { int dist, node; };

int main() { int t; cin >> t;

while (t--) { int n, m, S; cin >> n >> m >> S;

vector<int> dist(n + 1, -1);
dist[S] = 0;

priority_queue<Pair, vector<Pair>, greater<Pair>> pq;
pq.push(make_pair(0, S));

vector<pair<int, int>> graph[n + 1];

for (int i = 0; i < m; ++i) {
  int u, v, w;
  cin >> u >> v >> w;
  graph[u].push_back(make_pair(v, w));
}

while (!pq.empty()) {
  int u = pq.top().second;
  pq.pop();

  for (auto v : graph[u]) {
    int newDist = dist[u] + v.second;

    if (dist[v.first] == -1 || dist[v.first] > newDist) {
      dist[v.first] = newDist;
      pq.push(make_pair(newDist, v.first));
    }
  }
}

for (int i = 1; i <= n; ++i) {
  if (i != S) {
    cout << dist[i] << endl;
  }
}

}

return 0; }