拓扑排序 JAVA实现

问题描述

假设给我们一个任意的图,它可能是也可能不是DAG(有向无圈图),推广拓扑排序算法,以使得给定有向图G的输入,它的输出是以下两者之一:
(a) 一个拓扑排序,于是确定了G为DAG;
或者
(b) G中的一个圈,于是确定了G不是DAG.

输入

第一行两个数n,m,代表节点数和边数
m行,每行两个数代表一条有向边

输出

YES
一个拓扑序,数字之间用逗号分隔。
或者
NO
一个圈,数字之间用逗号分隔。

JAVA实现

package sort;

import java.util.Iterator;
import java.util.Scanner;
import java.util.Vector;

public class Main {

    public static void main(String[] args) {

        //用于输出的vector
        Vector out = new Vector ();

        Scanner sc = new Scanner(System.in);
        int n=sc.nextInt();
        int m=sc.nextInt();

        int[][] matrix=new int[n][n];

//      outMatrix(matrix);

//      System.out.println("-------------------------------");

/*      给矩阵赋值*/
        for(int i=0;i1][sc.nextInt()-1]=1;
        }

//      outMatrix(matrix);//

        sc.close();

        for(int i=0;i//依次检查第i列,即为i+1号定点的输入量
            if(!out.contains(i+1)){ //i+1号还没有成功输出
                boolean goon=true;
                int j=0;
                while(goon){
                    if(matrix[j][i]==0){ //i+1号没有来自j+1号的输入
                        if(j!=n-1) j++;
                        else{ 
                            out.add(i+1); 
                            goon=false;
                            //清除此顶点的输出边
                            for(int k=0;k0;
                            }
                            i=-1;
                        }


                    }else{ //有输入
                        goon=false;
                    }
                }
            }
        }

//      System.out.println(out.size());


    /*  遍历输出结果*/
        int comma=1;
        if(out.size()==n){//是DAG 输出拓扑排序

            System.out.println("YES");

            Iterator iter = out.iterator();

            while(iter.hasNext()){

            int value = (int)iter.next();

            if(comma!=n){
                System.out.print(value+",");
                comma+=1;
              }else System.out.print(value);


            }
        }else{//不是DAG 输出圈

/*          已经扔出了部分DAG,这些肯定不在某个圈里。
            再扔出所有“死路”有输入没有输出的点。
            剩下的点一定属于某个圈中。*/

            System.out.println("NO");

            Vector Noout = new Vector ();

            for(int i=0;i1;i++){

                if(!out.contains(i+1)){ //i+1号还没被扔进垃圾桶
                    boolean goon=true;
                    int j=0;
                    while(goon){
                        if(matrix[i][j]==0){ //i+1号没有给j+1号输出
                            if(j!=n-1) j++;
                            else{ 
                                out.add(i+1); //此时out不再存储拓扑排序序列,而是“垃圾桶”
                                goon=false;
                                //清除此顶点的输入边
                                for(int k=0;k0;
                                }
                                i=-1;
                            }


                        }else{ //有输入
                            goon=false;
                        }
                    }
                }
            }
/*          输出一个圈*/
            //确保第一个顶点是在某个环里面
            int first=0;
            while(out.contains(first+1)){
                first+=1;
            }
            Noout.add(first+1);
            boolean loop=true;
            while(loop){
                for(int i=0;iif(matrix[first][i]==1){//找到下一个顶点i+1号
                        if( Noout.contains(i+1)){//已经有i+1号了,说明找到一个环
                            first=i;//环的开头顶点
                            loop=false;
                            break;
                        }
                        Noout.add(i+1);
                        first=i;
                        i=-1;

                    }
                }


            }

            //最终输出 从first开始

            boolean begin=false;

            Iterator it = Noout.iterator();
//          System.out.println("Here!!");
//          System.out.println(Noout.size());

            while(it.hasNext()){

            int value = (int)it.next();

            if(value==first+1){
                    begin=true;
                }

            if(begin){
                    System.out.print(value+",");
                }
            }

            System.out.print(first+1);


        }

    }


    //输出矩阵
    static void outMatrix (int [][] matrix){
        for(int i=0;ifor(int j=0;j" ");    
            }
             System.out.println();
        }
    }

}

结果展示

输入:
5 5
1 2
1 3
2 5
3 4
4 5

输出:
YES
1,2,3,4,5

输入:
5 7
1 2
1 3
2 1
2 5
3 4
4 2
4 5

输出:
NO
1,2,1

你可能感兴趣的:(算法,java,算法-图-拓扑排序)