import java.util.*;

/**
* 图的拓扑排序
* 1)从图中找到所有入度为0的点输出
* 2)把图中入度为0的点删掉,继续寻找入度为0的点输出,周而复始
* 3)图的所有节点被删除后,依次输出的顺序就是拓扑排序
* 要求:有向图且无环
* 应用:事件安排、编译顺序
*/
public class TopoSort {

// 图有向且无环
public static List<Node> sortedTopology(Graph graph) {
// key:某一个node
// value:剩余的入度
HashMap<Node, Integer> inMap = new HashMap<>();
// 剩余入度为0的点,才能进这个队列
Queue<Node> zeroInQueue = new LinkedList<>();

for (Node node : graph.nodes.values()) {
inMap.put(node, node.in);
if (node.in == 0) {
zeroInQueue.add(node);
}
}
// 拓扑排序的结果,依次加入result
List<Node> result = new ArrayList<>();
while (!zeroInQueue.isEmpty()) {
Node cur = zeroInQueue.poll();
result.add(cur);
for (Node next : cur.nexts) {
inMap.put(next, inMap.get(next) - 1);
if (inMap.get(next) == 0) {
zeroInQueue.add(next);
}
}
}
return result;
}

class Graph {

public HashMap<Integer, Node> nodes;

public HashSet<Edge> edges;

public Graph() {
nodes = new HashMap<>();
edges = new HashSet<>();
}

}

class Node {

public int value;

public int in;

public int out;

public ArrayList<Node> nexts;

public ArrayList<Edge> edges;

public Node(int value) {
this.value = value;
nexts = new ArrayList<>();
edges = new ArrayList<>();
}

}

class Edge {

// 权重
public int weight;

public Node from;

public Node to;

public Edge(int weight, Node from, Node to) {
this.weight = weight;
this.from = from;
this.to = to;
}

}

}

/* 如有意见或建议,欢迎评论区留言;如发现代码有误,欢迎批评指正 */