算法期中——拓扑序[Special judge]

来源:互联网 发布:python开发入门详解 编辑:程序博客网 时间:2024/06/05 11:59

拓扑序[Special judge]


题目

Description
在图论中,拓扑序(Topological Sorting)是一个有向无环图(DAG, Directed Acyclic Graph)的所有顶点的线性序列. 且该序列必须满足下面两个条件:

  1. 每个顶点出现且只出现一次.
  2. 若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面.

对于一个含有n个节点的有向无环图(节点编号0到n-1),输出它的一个拓扑序.

图的节点数和边数均不多于100000,保证输入的图是一个无环图.

请为下面的Solution类实现解决上述问题的topologicalSort函数,函数参数中n为图的节点数,edges是边集,edges[i]表示第i条边从edges[i].first指向edges[i].second. 函数返回值为有向图的一个拓扑序. 有向图有多个拓扑序时,输出任意一个即可.

class Solution {public:    vector<int> topologicalSort(int n, vector<pair<int, int>>& edges){    }};

例1:
n = 3,edges = {(0, 1), (0, 2)},函数应返回{0, 1, 2}或者{0, 2, 1}.

例2:
n = 4,edges = {(0, 1), (0, 2), (1, 2), (3, 0)},函数应返回{3, 0, 1, 2}.


解析

拓扑排序:将有向图中的顶点以线性方式进行排序。即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点v的前面。

过程:

  1. 从 DAG 图中选择一个 没有前驱(即入度为0)的顶点并输出。
  2. 从图中删除该顶点和所有以它为起点的有向边。
  3. 重复 1 和 2 直到当前的 DAG 图为空或当前图中不存在无前驱的顶点为止。后一种情况说明有向图中必然存在环。

解决

class Solution {public:    vector<int> topologicalSort(int n, vector<pair<int, int>>& edges) {        vector<int> result;        // 构造有向无环图        vector<unordered_set<int>> graph = makeGraph(n, edges);        // 计算每个节点的入度        vector<int> degrees = computeIndegree(graph);        queue<int> zero;        for (int i = 0; i < n; i++) {            if (degrees[i] == 0) {                zero.push(i);            }        }        for (int i = 0; i < n; i++) {            // 图中一定有一个入度为0的点            if (zero.empty()) return {};            int temp = zero.front();            zero.pop();            result.push_back(temp);            // 进行删去点temp的操作,使得相应的点的入度减1            for (unordered_set<int>::iterator it = graph[temp].begin(); it != graph[temp].end(); it++) {                degrees[*it]--;                // 如果操作后点入度为0,则压进队列                if (degrees[*it] == 0) {                    zero.push(*it);                }            }        }        return result;    }    vector<unordered_set<int>> makeGraph(int n, vector<pair<int, int>>& edges) {        vector<unordered_set<int>> result(n);        int num = edges.size();        for (int i = 0; i < num; i++) {            result[edges[i].first].insert(edges[i].second);        }        return result;    }    vector<int> computeIndegree(vector<unordered_set<int>> graph) {        int num = graph.size();        vector<int> result(num, 0);        for (int i = 0; i <num; i++) {            int temp = graph[i].size();            for (unordered_set<int>::iterator it = graph[i].begin(); it != graph[i].end(); it++) {                result[*it]++;            }        }        return result;    }};
原创粉丝点击