//使用map模拟邻接表(查询快),判断有向无环图是否存在环,或者是否可以进行排序
import java.util.*;
public class Tuopusort {
public static void main(String args[]){
Scanner in=new Scanner(System.in);
while(in.hasNext()){
int n=in.nextInt();
int m=in.nextInt();
int du[]=new int[n+1]; //存储度
Map<String,Integer> map=new HashMap<String,Integer>(); //模拟邻接表存储
int x,y;
String str=new String("");
for(int i=0;i<m;i++){
x=in.nextInt();
y=in.nextInt();
str=x+" "+y;
if(!map.containsKey(str)){ //判断重复边
map.put(str,i);
du[y]+=1;
}
}
Queue<Integer> queue=new LinkedList<Integer>(); //用于排序的队列
Queue<Integer> ans=new LinkedList<Integer>(); //用于保存结果的队列
for(int i=1;i<=n;i++){
if(du[i]==0){
queue.offer(i);
ans.offer(i);
du[i]=-1;
}
}
int temp=-1;
int count=0;
String str2=new String(" ");
while(queue.size()>0){
if(queue.size()>1){
System.out.println("存在点无法判断先后");
return;
}
temp=queue.poll();
count++;
for(int i=1;i<=n;i++){
if(map.containsKey(temp+" "+i)){
du[i]--;
if(du[i]==0){
queue.offer(i);
ans.offer(i);
du[i]=-1;
}
}
}
}
//判断是否存在环路
if(count==n){
System.out.println("拓扑排序");
int flag=1;
while(ans.size()>0){
if(flag==1){
System.out.print(ans.poll());
flag=0;
}else{
System.out.print(" "+ans.poll());
}
}
System.out.println();
}else{
System.out.println("存在环路");
}
}
}
}
//使用邻接矩阵 import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; public class test1 { //邻接矩阵 static int[][] graph = new int[200][200]; //结点个数和边的个数 static int vNum,eNum; //记录每个结点的入度,初始化为0 static int[] count = new int[200]; //用队列保存拓扑序列 static Queue<Integer> queue = new LinkedList<>(); //拓扑排序 void topoSort(){ //入度为0的结点的个数,也就是入队个数 int number = 0; //暂时存放拓扑序列 Queue<Integer> temp = new LinkedList<Integer>(); //遍历图中所有结点,找入度为0的结点删除(放进队列) for(int i=1;i<=vNum;i++){ if(count[i] == 0){ queue.offer(i); } } //删除这些被删除结点的出边(即对应结点入度减一) while(!queue.isEmpty()){ int i = queue.peek(); temp.offer(queue.poll()); number++; for(int j=1;j<=vNum;j++){ if(graph[i][j] == 1){ count[j] -= 1; //出现了新的入度为0的结点,删除 if(count[j] == 0){ queue.offer(j); } } } } if(number != vNum){ System.out.println("最后存在入度为1的结点,这个有向图是有回路的。"); }else{ System.out.println("这个有向图不存在回路,拓扑序列为:" + temp.toString()); } } //创建图,以邻接矩阵表示 void create(){ Scanner sc = new Scanner(System.in); System.out.println("正在创建图,请输入顶点个数vNum:"); vNum = sc.nextInt(); System.out.println("请输入边个数eNum:"); eNum = sc.nextInt(); //初始化邻接矩阵为0(如果3个顶点,顶点分别是1,2,3) for(int i=1;i<=vNum;i++){ for(int j=1;j<=vNum;j++){ graph[i][j] = 0; } } //输入边的情况 System.out.println("请输入边的头和尾:"); for(int k=1;k<=eNum;k++){ int i = sc.nextInt(); int j = sc.nextInt(); graph[i][j] = 1; } //计算每个结点的入度 Arrays.fill(count, 0);//先初始化为0 for(int i=1;i<=vNum;i++){ for(int j=1;j<=vNum;j++){ if(graph[i][j] == 1){ count[j] = count[j] + 1; } } } } public static void main(String[] args) { test1 t = new test1(); t.create(); t.topoSort(); } }