DAG 即有向无环图,用 DAG 可以描述一些有依赖关系的任务组,而这些任务还有另一个属性,即都有一个权重,标示这个任务的重要性,我们需要你实现一个算法,对 DAG 里面的节点进行排序,保证排序不违背 DAG 的依赖关系,即有一个任务 A如果排在任务 B 前面,那么在 DAG 中不能存在有 B 到A的路径,另外有一个要求是,让权重大的任务尽量优先执行输入: 在第一行给定 DAG 的节点数n 和边数 e,后面n 行,每一行是节点的标号和权重,最后e 行是边的描述 排序好的节点标号,在一行内输出,用空格隔开。 输入样例:44 12 23 35 44 12 13 24 34 输出样例: 1 3 2 4
时间: 2024-03-22 22:37:50 浏览: 72
dag-comparisons:用于比较、聚合和聚类有向无环图 (DAG) 的算法
可以利用拓扑排序的思想来实现。首先统计每个节点的入度,然后将入度为0的节点加入到一个队列中。接着不断从队列中取出节点,将其加入结果集中,并将其所有出边指向的节点的入度减1。如果某个节点的入度减为0,就将其加入队列中。最后,如果结果集中的节点数小于总节点数,说明图中存在环,无法进行拓扑排序。
在实现过程中,可以用一个哈希表(unordered_map)来存储每个节点的权重。具体实现如下:
```c++
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
using namespace std;
vector<int> topological_sort(int n, const vector<pair<int, int>>& edges, const unordered_map<int, int>& weights) {
// 统计每个节点的入度
vector<int> in_degree(n + 1);
for (const auto& [u, v] : edges) {
in_degree[v]++;
}
// 将入度为0的节点加入队列中
queue<int> q;
for (int i = 1; i <= n; i++) {
if (in_degree[i] == 0) {
q.push(i);
}
}
// 依次取出队列中的节点,将其加入结果集中,并更新其所有出边指向的节点的入度
vector<int> result;
while (!q.empty()) {
int u = q.front();
q.pop();
result.push_back(u);
for (const auto& [v, w] : edges) {
if (v == u) {
in_degree[w]--;
if (in_degree[w] == 0) {
q.push(w);
}
}
}
}
// 如果结果集中的节点数小于总节点数,说明图中存在环,无法进行拓扑排序
if (result.size() < n) {
throw runtime_error("The graph contains a cycle!");
}
// 按照节点权重从大到小排序
sort(result.begin(), result.end(), [&](int a, int b) {
return weights.at(a) > weights.at(b);
});
return result;
}
int main() {
int n, e;
cin >> n >> e;
// 存储每个节点的权重
unordered_map<int, int> weights;
for (int i = 1; i <= n; i++) {
int id, weight;
cin >> id >> weight;
weights[id] = weight;
}
// 存储有向边
vector<pair<int, int>> edges(e);
for (int i = 0; i < e; i++) {
cin >> edges[i].first >> edges[i].second;
}
// 进行拓扑排序并按照节点权重从大到小排序
try {
vector<int> result = topological_sort(n, edges, weights);
for (int i = 0; i < n; i++) {
cout << result[i];
if (i < n - 1) {
cout << " ";
}
}
cout << endl;
} catch (const runtime_error& e) {
cerr << e.what() << endl;
}
return 0;
}
```
在上述代码中,首先读入节点个数和边数,然后分别读入每个节点的编号和权重,以及每条有向边的起点和终点。接着调用topological_sort()函数进行拓扑排序,并按照节点权重从大到小排序。如果图中存在环,会抛出一个异常。最后输出排序后的节点编号。
阅读全文