1.拓扑排序
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边<u,v>∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列
2.实现方法
利用二维数组保存有向图,重复边过滤,有边的话map[i][j]=1,i到j存在着边,用一个indegree数组保存每个节点的入度信息,
从度为0的节点开始,入栈,若栈不为空,出栈,当前元素到其他元素若存在边,去除这条边,map[i][j]=0,此外,让边的末尾节点入度减1,若减为0,则重新入栈,并且将此顶点入度去掉
3.代码实现
package 有向图的拓扑排序;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack;
/**
* @Author:likui
* @PacakgeName:test
* @Description: 拓扑排序
* 3 1 5 21 10 孩子节点
* 0 3 3 1 5 父节点
* 3 指定节点
* @Date:Created in 9:04 2019/9/7
*/
public class Main {
public static void way(int []x,int y[],int pos,int max){
int indegree[]=new int[max];//保存每个顶点的入度信息
int map[][]=new int[max][max];//保存整个有边的图
for (int i = 0; i <x.length ; i++) {
if (x[i]==0||y[i]==0)//去掉顶点为0的输入,过滤条件
continue;
else
{
if (map[x[i]-1][y[i]-1]==0){//保存边,重复边去掉,map[i][j]=1,说明有i到j的有向边
map[x[i]-1][y[i]-1]=1;
indegree[y[i]-1]++;
}
}
}
System.out.println("拓扑排序结果:");
System.out.println(BFS(indegree,map,pos));
}
private static ArrayList<Integer> BFS(int []indegree,int[][] map,int pos) {
ArrayList<Integer> list=new ArrayList<>();//保存拓扑排序
Stack<Integer> stack = new Stack<>();
//indegree[pos-1]=-1; //从指定位置开始进行拓扑排序
for (int i = 0; i <map.length ; i++) {//去掉没有边的节点的图
for (int j = 0; j <map.length ; j++) {
if (map[i][j]!=0&&indegree[i]==0&&i==pos-1)
{
stack.push(i);//将入度为0的节点入栈
indegree[i] = -1;
}
}
}
/* for (int i = 0; i < indegree.length; i++) {//整个图的拓扑排序,包含没有边的节点
if (indegree[i] == 0) {
stack.push(i);
indegree[i] = -1;
}
}*/
while (!stack.isEmpty()) {//若栈不为空
int p = stack.pop();//出栈
// count++;
list.add(p+1);//访问当前元素
for (int j = 0; j < indegree.length; j++) {
if (map[p][j] == 1) {//当前度为0的节点到其他顶点有边
map[p][j] = 0;//去掉这条边
indegree[j]--;//变得末尾节点入度减1
if (indegree[j] == 0) {//如果度减为0,入栈
stack.push(j);
indegree[j] = -1;//没有入度信息
}
}
}
}
return list;
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
String s1=sc.nextLine();
String s2=sc.nextLine();
int pos=Integer.parseInt(sc.nextLine());
String str1[]=s1.split(" ");
String str2[]=s2.split(" ");
int x[]=new int[str1.length];
int y[]=new int[str2.length];
int max1=Integer.MIN_VALUE;
int max2=Integer.MIN_VALUE;
for (int i = 0; i <x.length ; i++) {
x[i]=Integer.parseInt(str2[i]);
y[i]=Integer.parseInt(str1[i]);
max1=Math.max(y[i],max1);
max2=Math.max(x[i],max2);
}
max1=Math.max(max1,max2);
way(x,y,pos,max1);
}
}
4.输出测试用例结果,0代表不存在的节点