Open In App

CSES Solutions – Course Schedule

Last Updated : 19 May, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

You have to complete n courses. There are m requirements of form "course a has to be completed before course b". Your task is to find an order in which you can complete the courses.

Examples:

Input: n = 5, m = 3, requirements[][] = {{1, 2}, {3, 1}, {4, 5}}
Output: 3 4 1 5 2
Explanation:

  • Since course 3 and 4 have no requirements, we can complete course 3 and 4.
  • After completing course 3, we can complete course 1.
  • After completing course 4, we can complete course 5.
  • After completing course 1, we can complete course 2.

Input: n = 4, m = 2, requirements[][] = {{4, 2}, {3, 1}}
Output: 3 4 1 2
Explanation:

  • Since course 3 and 4 have on requirements, we can complete course 3 and 4.
  • After completing course 3, we can complete course 1.
  • After completing course 4, we can complete course 2.

Approach: To solve the problem, follow the below idea:

The problem can be solved using Topological Sort. Each course can be considered as a node and each requirement (a, b) can be considered as a directed edge from node a to node b. Now, we can find the topological sort of the graph to find the order in which courses can be completed.

Step-by-step approach:

  • Construct a graph of N nodes for N courses.
  • For every requirement, draw directed edges between the nodes and keep track of the indegree of each node.
  • Maintain a queue to keep track of nodes which we can visit next.
  • Push all the nodes with indegree 0 into the queue.
  • Till queue is not empty,
    • Pop the node at the front of the queue and push it into the ans vector.
    • Decrease the indegree of all the neighboring nodes by 1.
    • If the indegree of neighboring node becomes 0, push the neighboring node to the queue.
  • After the queue becomes empty, print the ans vector as the final answer.

Below is the implementation of the algorithm:

C++
#include <bits/stdc++.h>
using namespace std;

// Function to perform topological sort and find the order
// in which courses can be completed
vector<int> solve(int n, vector<vector<int> >& adj,
                  vector<int>& indeg)
{
    queue<int> q;
    vector<int> ans;
    // Initialize queue with nodes having in-degree 0
    for (int i = 1; i <= n; ++i) {
        if (indeg[i] == 0)
            q.push(i);
    }
    // Iterate till q is not empty
    while (!q.empty()) {
        // Pop the front node of the queue
        int node = q.front();
        q.pop();
        // Push the front node to the answer
        ans.push_back(node);
        // Update in degree of adjacent nodes
        for (int child : adj[node]) {
            indeg[child] -= 1;
            if (indeg[child] == 0) {
                q.push(child);
            }
        }
    }
    return ans;
}
int main()
{
    int n, m;
    // Sample input
    n = 5;
    m = 3;
    vector<pair<int, int> > requirements
        = { { 1, 2 }, { 3, 1 }, { 4, 5 } };
    vector<vector<int> > graph(n + 1);
    vector<int> indeg(n + 1, 0);
    // Build directed graph and calculate in-degrees
    for (int i = 0; i < m; ++i) {
        int u = requirements[i].first;
        int v = requirements[i].second;
        graph[u].push_back(v);
        indeg[v] += 1;
    }

    // Get the topological sort
    vector<int> ans = solve(n, graph, indeg);

    // Print the result
    if (ans.size() != n) {
        cout << "IMPOSSIBLE";
    }
    else {
        for (int i = 0; i < n; i++)
            cout << ans[i] << " ";
    }
    return 0;
}
Java
import java.util.*;

public class CourseSchedule {

    // Function to perform topological sort and find the
    // order in which courses can be completed
    public static List<Integer>
    solve(int n, List<List<Integer> > adj, int[] indeg)
    {
        Queue<Integer> q = new LinkedList<>();
        List<Integer> ans = new ArrayList<>();

        // Initialize queue with nodes having in-degree 0
        for (int i = 1; i <= n; ++i) {
            if (indeg[i] == 0) {
                q.add(i);
            }
        }

        // Iterate till q is not empty
        while (!q.isEmpty()) {
            // Pop the front node of the queue
            int node = q.poll();
            // Push the front node to the answer
            ans.add(node);
            // Update in-degree of adjacent nodes
            for (int child : adj.get(node)) {
                indeg[child] -= 1;
                if (indeg[child] == 0) {
                    q.add(child);
                }
            }
        }

        return ans;
    }

    public static void main(String[] args)
    {
        int n, m;
        // Sample input
        n = 5;
        m = 3;
        List<int[]> requirements = Arrays.asList(
            new int[] { 1, 2 }, new int[] { 3, 1 },
            new int[] { 4, 5 });

        List<List<Integer> > graph = new ArrayList<>(n + 1);
        for (int i = 0; i <= n; ++i) {
            graph.add(new ArrayList<>());
        }
        int[] indeg = new int[n + 1];

        // Build directed graph and calculate in-degrees
        for (int[] req : requirements) {
            int u = req[0];
            int v = req[1];
            graph.get(u).add(v);
            indeg[v] += 1;
        }

        // Get the topological sort
        List<Integer> ans = solve(n, graph, indeg);

        // Print the result
        if (ans.size() != n) {
            System.out.println("IMPOSSIBLE");
        }
        else {
            for (int i = 0; i < n; ++i) {
                System.out.print(ans.get(i) + " ");
            }
        }
    }
}

// This code is contributed by shivamgupta0987654321
Python
from collections import deque, defaultdict

# Function to perform topological sort and find the order
# in which courses can be completed


def solve(n, adj, indeg):
    q = deque()
    ans = []

    # Initialize queue with nodes having in-degree 0
    for i in range(1, n + 1):
        if indeg[i] == 0:
            q.append(i)

    # Iterate till q is not empty
    while q:
        # Pop the front node of the queue
        node = q.popleft()
        # Push the front node to the answer
        ans.append(node)
        # Update in degree of adjacent nodes
        for child in adj[node]:
            indeg[child] -= 1
            if indeg[child] == 0:
                q.append(child)

    return ans


def main():
    # Sample input
    n = 5
    m = 3
    requirements = [(1, 2), (3, 1), (4, 5)]
    graph = defaultdict(list)
    indeg = [0] * (n + 1)

    # Build directed graph and calculate in-degrees
    for u, v in requirements:
        graph[u].append(v)
        indeg[v] += 1

    # Get the topological sort
    ans = solve(n, graph, indeg)

    # Print the result
    if len(ans) != n:
        print("IMPOSSIBLE")
    else:
        print(" ".join(map(str, ans)))


if __name__ == "__main__":
    main()
# This code is contributed by Ayush Mishra
JavaScript
class CourseSchedule {
    // Function to perform topological sort and find the
    // order in which courses can be completed
    static solve(n, adj, indeg) {
        let q = [];
        let ans = [];

        // Initialize queue with nodes having in-degree 0
        for (let i = 1; i <= n; ++i) {
            if (indeg[i] === 0) {
                q.push(i);
            }
        }

        // Iterate till q is not empty
        while (q.length !== 0) {
            // Pop the front node of the queue
            let node = q.shift();
            // Push the front node to the answer
            ans.push(node);
            // Update in-degree of adjacent nodes
            for (let child of adj[node]) {
                indeg[child] -= 1;
                if (indeg[child] === 0) {
                    q.push(child);
                }
            }
        }

        return ans;
    }

    static main() {
        let n, m;
        // Sample input
        n = 5;
        m = 3;
        let requirements = [
            [ 1, 2 ], [ 3, 1 ], [ 4, 5 ]
        ];

        let graph = new Array(n + 1).fill(null).map(() => []);
        let indeg = new Array(n + 1).fill(0);

        // Build directed graph and calculate in-degrees
        for (let req of requirements) {
            let u = req[0];
            let v = req[1];
            graph[u].push(v);
            indeg[v] += 1;
        }

        // Get the topological sort
        let ans = CourseSchedule.solve(n, graph, indeg);

        // Print the result
        if (ans.length !== n) {
            console.log("IMPOSSIBLE");
        } else {
            console.log(ans.join(" "));
        }
    }
}

// Call the main function
CourseSchedule.main();

Output
3 4 1 5 2 

Time Complexity: O(N)
Auxiliary Space: O(N)


Next Article
Practice Tags :

Similar Reads