拓扑排序-判断有无环或者有无点无法区分先后顺序

//使用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();
    }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值