Uva10305-Ordering Tasks(拓扑排序)
题目链接
题意
给你n、m,n代表点的个数,m代表边的条数,然后下面给出m条边,都是有向的(有向图),要你建出一个图,并且找出一种序列,这种序列叫做拓扑序列 。
拓扑排序 是对有向无环图(DAG)进行的一种操作,这种操作是将DAG中的所有顶点排成一个线性序列,使得图中的任意一对顶点u,v满足如下条件:若边(u,v)∈E(G),则u在最终的线性序列中出现在v的前面;
拓扑排序的应用常常和AOV网相联系,在一个大型的工程中,某些项目不是独立于其他项目的,这意味着这种非独立的项目的完成必须依赖与其它项目的完成而完成,不妨记为u,v,则若边(u,v)∈E(G),代表着必须在项目u完成后,v才能完成。
解析
拓扑排序使用BFS解题的过程:
- 找出入度为0的结点并加入队列;
- 在队列中弹出一个结点,并访问,并把它的相邻结点的入度-1,如果减一之后入度为0,则也进队列;
- 直到队列为空,访问完毕 ;
import java.io.BufferedInputStream;
import java.util.*;
public class UVA10305_OrderingTasks { //提交时改成main
//点
private static class Node{
public int value;
public int in;
public ArrayList<Node> nexts;
public Node(int value) {
this.value = value;
in = 0;
nexts = new ArrayList<>();
}
}
//图
private static class Graph{
public HashMap<Integer,Node>nodes; //结点的集合
public Graph() {
nodes = new HashMap<>();
}
}
public static void main(String[] args) {
Scanner cin = new Scanner(new BufferedInputStream(System.in));
while(cin.hasNext()){
int n = cin.nextInt();
int m = cin.nextInt();
if(n == 0 && m == 0)break;
Graph graph = createGraph(cin,n,m);
sortedTopology(graph);
}
}
//建图
public static Graph createGraph(Scanner cin,int n,int m){
Graph graph = new Graph();
for(int i = 1; i <= n; i++)graph.nodes.put(i,new Node(i)); //一开始每个都有
int a,b;
for(int i = 0; i < m; i++){
a = cin.nextInt();
b = cin.nextInt();
if(!graph.nodes.containsKey(a))graph.nodes.put(a,new Node(a)); //一定要注意先判断一下
if(!graph.nodes.containsKey(b))graph.nodes.put(b,new Node(b));
Node from = graph.nodes.get(a);
Node to = graph.nodes.get(b);
to.in++;
from.nexts.add(to); //相邻结点
}
return graph;
}
//拓扑排序
private static void sortedTopology(Graph graph){
Queue<Node>zque = new LinkedList<>();
HashMap<Node,Integer> inMap = new HashMap<>(); //为了不改变原来的图 key存结点 value存入度
for(Node node : graph.nodes.values()){
inMap.put(node,node.in);
if(node.in == 0){
zque.add(node);
}
}
boolean flag = true; //为了输出
while(!zque.isEmpty()){
Node cur = zque.poll();
if(flag){
System.out.print(cur.value);
flag = false;
}
else System.out.print(" " + cur.value);
for(Node next : cur.nexts){
inMap.put(next,inMap.get(next)-1); //相邻的地方入度减一
if(inMap.get(next) == 0){
zque.add(next);
}
}
}
System.out.println();
}
}