Topological sorting of hand-in-hand Teaching
In graph theory, * * Topological Sorting Is a linear sequence of all vertices of a directed acyclic graph (DAG) * *. And the sequence must meet the following two conditions:
- Each vertex appears only once.
- If there is A path from vertex A to vertex B, vertex A appears in front of vertex B in the sequence.
Only directed acyclic graphs (DAG) have topological sorting, and non DAG graphs have no topological sorting.
Topological sorting is generally applicable to dependent directed graphs, and can also be used to detect whether there are rings in directed graphs
process
-
Mapping
-
Record the penetration of each point
-
Add the points that do not have access to the queue to see the dependency update access later
-
Repeat 3 until the queue is empty
Tip: a pointless point is actually a point that has no dependency, that is, it can be accessed without other conditions
Mapping
I generally have three implementation forms
-
Implement your own graph class
-
Map < int, vector < int > >
-
Or use the form of adjacency table vector < list < int > >
Algorithm flow
Implementation of self graph class
class Graph { public: Graph(int n) { n_ = n; lst_.resize(n, list<int>()); degree_.resize(n, 0); } void add(int v, int u) { lst_[v].push_back(u); ++degree_[u]; } private: vector<list<int>> lst_; // Adjacency table vector<int> degree_; // Penetration };
Examples
Simple version
207. Curriculum
Medium difficulty 916
You must take numCourses this semester, marked 0 to numCourses - 1.
Some prerequisite courses are required before taking some courses. Prerequisite courses are given by the array prerequisites, where prerequisites[i] = [ai, bi], which means that if you want to learn course ai, you must learn course bi first.
- For example, the prerequisite course pair [0, 1] indicates that if you want to learn course 0, you need to complete course 1 first.
Please judge whether it is possible to complete all courses? If yes, return true; Otherwise, false is returned.
Example 1:
Input: numCourses = 2, prerequisites = [[1,0]] Output: true Explanation: there are 2 courses in total. You need to complete course 0 before learning course 1. This is possible.
Example 2:
Input: numCourses = 2, prerequisites = [[1,0],[0,1]] Output: false Explanation: there are 2 courses in total. Before learning course 1, you need to complete course 0; You should also complete course 1 before studying course 0. It's impossible.
Tips:
- 1 <= numCourses <= 105
- 0 <= prerequisites.length <= 5000
- prerequisites[i].length == 2
- 0 <= ai, bi < numCourses
- All course pairs in prerequisites[i] are different from each other
class Solution { public: bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { int n=prerequisites.size(); vector<int> degree(numCourses,0); // Initialization penetration is 0 // Mapping with adjacency table vector<list<int>> mp(numCourses); for(int i=0;i<n;i++) { mp[prerequisites[i][1]].push_back(prerequisites[i][0]); degree[prerequisites[i][0]]++; } // Start topology sorting queue<int> que; int count = 0; // How many points have been recorded for(int i=0;i<degree.size();i++) { if(degree[i]==0) { que.push(i); } } while(!que.empty()) { // The queue cannot be empty int val = que.front(); que.pop(); count++; auto vec = mp[val]; for(auto i=vec.begin();i!=vec.end();i++) { degree[*i]--; // Update penetration if(degree[*i]==0) { // Join the queue with a penetration of 0 que.push(*i); } } } if(count==numCourses) { // exannulate return true; } return false; // Ring } };
851. Noisy and rich
Medium difficulty 184
There are a group of n people as experimental subjects, numbered from 0 to n - 1, in which each person has different amounts of money and different degrees of quiet. For convenience, we call the person numbered X "person x" for short.
Give you an array richer, where richer[i] = [ai, bi] means that person ai has more money than person bi. Give you another integer array quiet, where quiet[i] is the quiet value of person i. The data logic given in richer is self consistent (that is, while person x is richer than person y, person y is not richer than person x).
Now, return an integer array answer as the answer, where answer[x] = y on the premise that person y is the quietest person (that is, the person with the smallest quiet value quiet[y]) among all people who must have no less than person x.
Example 1:
Input: richer = [[1,0],[2,1],[3,1],[3,7],[4,3],[5,3],[6,3]], quiet = [3,2,5,4,6,1,7,0] Output:[5,5,2,5,4,5,6,7] Explanation: answer[0] = 5, person 5 than person 3 More money, person 3 than person 1 More money, person 1 than person 0 There is more money. Only quiet (with low quiet value) quiet[x])Who are you person 7, But it is unclear whether he is better than person 0 More money. answer[7] = 7, In all, you must have no less than person 7 Of people (this may include person 3,4,5,6 And 7), Quietest (with lower quiet value) quiet[x])Who are you person 7. Other answers can be explained by similar reasoning.
Example 2:
Input: richer = [], quiet = [0] Output:[0]
Tips:
- n == quiet.length
- 1 <= n <= 500
- 0 <= quiet[i] < n
- All values of quiet are different from each other
- 0 <= richer.length <= n * (n - 1) / 2
- 0 <= ai, bi < n
- ai != bi
- All number pairs in richer are different from each other
- The observation of richer is logically consistent
class Solution { public: vector<int> loudAndRich(vector<vector<int>>& richer, vector<int>& quiet) { degree_.resize(quiet.size(),0); vector<list<int>> graph_(quiet.size()); /* First build the map */ for(auto v : richer) { // cout<<v[0]<<" "<<v[1]<<endl; graph_[v[0]].push_back(v[1]); // It represents the rich and points to the poor degree_[v[1]]++; } vector<int> ans(quiet.size(),-1); for(int i=0;i<ans.size();i++) { ans[i] = i; } // Start traversal // First, find the point with a penetration of 0, and if the penetration is 1, the result is yourself queue<int> que; for(int i=0;i<degree_.size();i++) { if(degree_[i]==0) { que.push(i); } } while(!que.empty()) { int index = que.front(); que.pop(); // cout<<"index: "<<index<<endl; for(auto v : graph_[index]) { // cout<<"v: "<<v<<endl; if(quiet[ans[v]]>quiet[ans[index]]) { ans[v]=ans[index]; } degree_[v]--; if(degree_[v]==0) { que.push(v); } } } return ans; } private: vector<int> degree_; // Record penetration // vector<list<int>> graph_; };