sicily Ordering Tasks 拓扑排序

前言

真的很不喜欢sicily,有事没事就丢个wrong answer,不过还是因为自己编程习惯不太好

题目

Description

John has n tasks to do. Unfortunately, the tasks are not independent and the execution of one task is only possible if other tasks have already been executed.

Input

There are multiple test cases. The first line contains an integer T, indicating the number of test cases. Each test case begins with a line containing two integers, 1 <= n <= 100000 and 1 <= m <= 100000. n is the number of tasks (numbered from 1 to n) and m is the number of direct precedence relations between tasks. After this, there will be m lines with two integers i and j, representing the fact that task i must be executed before task j. It is guaranteed that no task needs to be executed before itself either directly or indirectly.

Output

For each test case, print a line with n integers representing the tasks in a possible order of execution. To separate them, print exactly one space after each integer. If there are multiple solutions, output the smallest one by lexical order.

Sample Input

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

Sample Output

5 3 2 4 1

拓扑排序

由AOV网构造拓扑序列的拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止。
(1) 选择一个入度为0的顶点并输出之;
(2) 从网中删除此顶点及所有出边。
循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,否则输出的顶点序列就是一种拓扑序列

一个AOV网应该是一个有向无环图,即不应该带有回路,<A,B>边表示B活动必须在A活动之后,<B,C>边表示C活动必须在B活动之后。

代码

//
// main.cpp
// Ordering Tasks
//
// Created by 邱兆丰 on 07/12/2016.
// Copyright © 2016 菇生. All rights reserved.
//

#include <iostream>
#include <queue>
#include <vector>
#include <memory.h>

const int MAXN = 100005;

using namespace std;

int main() {
    vector<int> AOV[MAXN];
    int indegree[MAXN];
    int testNum;
    cin >> testNum;
    while (testNum--) {
        // 初始化,很重要
        memset(indegree, 0, sizeof(indegree));

        int n, m;
        cin >> n >> m;
        int x, y;
        for (int i = 0; i < m; i++) {
            cin >> x >> y;
            indegree[y - 1]++;
            AOV[x - 1].push_back(y - 1);
        }
        priority_queue<int, vector<int>, greater<int>> q;
        // 把入度为0的点加入队列
        for (int i = 0; i < n; i++) {
            if (indegree[i] == 0) q.push(i);
        }
        while (!q.empty()) {
            int temp = q.top();
            q.pop();
            cout << temp + 1 << ' ';
            for (int i = 0; i < AOV[temp].size(); i++) {
                indegree[AOV[temp][i]]--;
                if (indegree[AOV[temp][i]] == 0) q.push(AOV[temp][i]);
            }
        }
        //最后根据n重置
        for (int i = 0; i < n; i++) {
            AOV[i].clear();
        }
        cout << endl;
    }
    return 0;
}

总结

1、因为题目要求数据可到100001,所以不能构建一个100001 * 100001的图,需用vector代替

2、由于要取字典序较小的,所以用到了priority_queue, 而这东西默认大的在前,需要priority_queue<int, vector<int>, greater<int>>

3、多组数据要养成初始化的习惯

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/mgsweet/article/details/53587598
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞