Problem
Basics
Topological Sorting
To perform Topological ordering of a Directed Acyclic Graph (DAG)G, all vertices in G are arranged into a linear sequence, making any pair of vertices u and v in the Graph. If the edge <u,v> E(G), then u appears before v in the linear sequence. Normally, such a linear sequence is referred to as a sequence satisfying Topological Order, short for Topological sequence
In graph theory, if a directed graph to set off from a vertex after several side back to that point, then the graph is a directed acyclic graph (DAG) because there is a point to the picture after two route to another point may not form a ring, so directed acyclic graph are not necessarily as tree, but any directed tree are directed acyclic graph
The topology sorting algorithm of topology sequence constructed by AOV network mainly performs the following two steps in a loop until there is no vertex with an entry degree of 0
1.Select a vertex with an input of 0 and output it
2.Deletes this vertex and all outgoing edges from the net
After the loop is completed, if the number of vertices output is less than the number of vertices in the network, loop information is output; otherwise, the output vertex sequence is a topology sequence
Analysis Process
1.This problem can be reduced to: is the course schedule a directed acyclic graph (DAG), that is, the courses stipulate preconditions, but cannot constitute any loop, otherwise the course preconditions will not be valid
2.The idea is to judge whether this course arrangement diagram is a directed acyclic graph (DAG) by topological sorting principle: sort the vertices of DAG, so that for each directed edge(u,v), there is u (in the sorting record) before v, which can also be understood as v for a point, only when all the source points of v appear, v can appear
3.The prerequisites list provides a prerequisite for obtaining the adjacency of course schedule diagram to reduce the time complexity of the algorithm
Entry table (Breadth first traversal)
Statistics the entry degree of each node in the curriculum schedule diagram is generated to generate the entry degree table indegrees
With a queue queue, all nodes with an entry degree of 0 are queued
When the queue is not empty, the first node in the queue will be queued in turn, and this node pre will be deleted in the course schedule diagram
This node pre is not really deleted from the adjacent list, but corresponds to the entry degree -1 of all the neighboring nodes
indegrees[cur] -= 1
When the entry degree of cur at the adjacent node is 0 after the entry degree of -1, it indicates that all precursor nodes of cur have been deleted, so the cur is joined in the team at this time
Execute numCourses–1 each time pre exits the queue
The whole course arrangement diagram is a directed acyclic graph (that is, it can be arranged), then all nodes must join and leave the queue, that is, complete the topological sorting. To put it another way, if there is a ring in the course arrangement diagram, there must be nodes with an entry degree not equal to 0 at all
Therefore, the topology sorts out the number of queues equal to the number of courses, and returns numCourses == 0 to determine whether the courses can be successfully arranged
Code
golang
func canFinish(numCourses int, prerequisites [][]int) bool {
if numCourses <= 0 {
return true
}
if len(prerequisites) == 0 || len(prerequisites[0]) == 0 {
return true
}
var
(
queue = make([]int, 0)
edges = make([][]int, numCourses) // The corresponding edge of the graph
preCnt = make(map[int]int) // 前置节点数
)
for _, p := range prerequisites { // Build the graph to find the next node list for all nodes
edges[p[1]] = append(edges[p[1]], p[0])
preCnt[p[0]] ++
// {0,1} duplicate arrays must not appear in the prerequisites,otherwise it will have to be done again
}
for i := 0; i < numCourses; i++ {
if preCnt[i] == 0 {
queue = append(queue, i)
}
}
// If the graph has no rings, then all nodes must be in and out of the queue
// If the graph does not have rings, then all nodes must be queued and queued out. If there are rings, then there are still nodes not traversed when the queue is empty, and then numCourses must not be 0
for len(queue) != 0 {
current := queue[0]
queue = queue[1:] // DeQueue
numCourses-- // A node was accessed
for _, v := range edges[current] {
preCnt[v]--
if preCnt[v] == 0 {
queue = append(queue, v)
}
}
}
return numCourses == 0
}
java
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {//A directed graph of numCourses nodes
int n=prerequisites.length;//n sides
ArrayList<Integer> [] adjacencyList=new ArrayList[numCourses];//邻接表
int [] inDegree=new int[numCourses];//The value of inDegree[i] indicates the degree of entry of node i
//The adjacency list is first constructed from the set of edges
for(int i=0;i<numCourses;i++){
adjacencyList[i]=new ArrayList<>();//The index of the node i is i
}
for (int [] pre:prerequisites) {
adjacencyList[pre[1]].add(pre[0]);//pre=[0,1],node 1 points to node 0
inDegree[pre[0]]++;
}
//Topological sort determines if it is a DAG
return topologicalSort(adjacencyList,inDegree,numCourses);
}
private boolean topologicalSort(ArrayList<Integer> [] adjacencyList,int [] inDegree,int n){
int res=0;//Topological sort the number of nodes that can be retrieved
Queue<Integer> queue=new LinkedList<Integer>();//Stores nodes with a degree of 0
for(int i=0;i<n;i++){
if(inDegree[i]==0) queue.offer(i);//Node i has an incoming degree of 0 and is added to the queue
}
while (!queue.isEmpty()) {
int i = queue.poll();//fetch node i
res++;
for (int child_of_i : adjacencyList[i]) {//For each node that node i points to
inDegree[child_of_i]--;
if (inDegree[child_of_i] == 0) queue.offer(child_of_i);
}
}
return res==n;