package correct_java_programs;
import java.util.*;

public class TOPOLOGICAL_ORDERING {
    public static ArrayList<Node> topological_ordering(List<Node> directedGraph) {
        ArrayList<Node> orderedNodes = new ArrayList<Node>();
        Queue<Node> processQueue = new LinkedList<>();

        // Map to store the count of predecessors for each node
        Map<Node, Integer> predecessorCount = new HashMap<>();

        // Initialize the predecessor count
        for (Node node : directedGraph) {
            predecessorCount.put(node, node.getPredecessors().size());
            // Add nodes with no predecessors to the processing queue
            if (node.getPredecessors().isEmpty()) {
                processQueue.add(node);
                orderedNodes.add(node);
            }
        }

        // Process the queue
        while (!processQueue.isEmpty()) {
            Node current = processQueue.poll();

            // Process each successor
            for (Node successor : current.getSuccessors()) {
                // Reduce the count of unprocessed predecessors for this successor
                int count = predecessorCount.get(successor) - 1;
                predecessorCount.put(successor, count);

                // If this successor has no other unprocessed predecessors, add to queue
                if (count == 0) {
                    processQueue.add(successor);
                    orderedNodes.add(successor);  // Ensures each node is added only once
                }
            }
        }

        // Check if all nodes are included in the sorted list (handles cycles or disconnected graphs)
        if (orderedNodes.size() != directedGraph.size()) {
            throw new RuntimeException("Graph has cycles or disconnected components");
        }

        return orderedNodes;
    }
}