(QR14)带权的DAG节点排序

Posted waitti

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(QR14)带权的DAG节点排序相关的知识,希望对你有一定的参考价值。

带权的DAG节点排序

DAG即Directed Acyclic Graph,有向无环图.用DAG可以描述一些有依赖关系的任务组,而这些任务还有另外一个属性,即都有一个权重,标示这个任务的重要性.
我们需要你来实现一个算法,对DAG里面的节点进行排序,保证排序不违背DAG的依赖关系,即一个任务A如果排在任务B前面,那么在DAG中不能存在由B到A的路径.另外一个要求就是,让权重大的任务尽量优先执行.

输入:在第一行给定DAG的节点数n和边数e.后面n行,每一行是 节点的 标号和权重, seq weight.最后e行,每一行是对于边的描述, s t.

输出:排序好的节点标号,在一行内输出,空格隔开.

有依赖关系的任务很显然需要拓扑排序,即每次都选择所有依赖任务已经做完的节点,此题每个节点额外有权重,优先选择权重高的即可。由于在拓扑排序中可以使用优先队列来选择度数为0的节点,所以只需要定义一个类,重载其小于号即可。

#include <bits/stdc++.h>

using namespace std;

const int N = 1010;

int a[N], degree[N];
vector<int> forword[N];

class Node{
public:
    int id;
    int deg;
    int weight;

    bool operator < (const Node & o) const{
        if(deg != o.deg)return deg < o.deg;
        return weight > o.weight;
    }
};

int main(){
    multiset<Node> que;
    int n, e, s, t, seq, w;
    cin >> n >> e;
    for(int i = 1;i <= n ; i++){
        cin >> seq >> w;
        a[seq] = w;
        forword[i] = vector<int>();
    }
    for(int i = 1;i <= e; i++){
        cin >> s >> t;
        degree[t]++;
        forword[s].push_back(t);
    }
    for(int i = 1;i <= n; i++){
//        cout << degree[i] << " " << a[i] << endl;
        que.insert({i, degree[i], a[i]});
    }
    int st = 0;
    while(st < n && !que.empty()){
        auto head = *que.begin();
        que.erase(que.begin());
        cout << head.id << " ";
        for(auto i:forword[head.id]){
            degree[i]--;
            que.insert({i, degree[i], a[i]});
        }
        st++;
    }
    cout << endl;
}

以上是关于(QR14)带权的DAG节点排序的主要内容,如果未能解决你的问题,请参考以下文章

赫夫曼树

画一棵带权为1、2、3、4的最优二叉树,计算它们的权

数据结构中赫夫曼树

Haffman编码

如何连接拓扑排序的 DAG 中的节点,以便每个上游节点最多可以到达任何下游节点 2 跳?

2017 计蒜之道 初赛 第三场 D. 腾讯狼人杀 (点边都带权的最大密度子图)