题解 | #【模板】拓扑排序#

【模板】拓扑排序

https://www.nowcoder.com/practice/88f7e156ca7d43a1a535f619cd3f495c

import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

/**
 * @BelongsProject: homework
 * @Author: Ling xi_Li
 * @CreateTime: 2023-11-07 10-20
 * @Description: TODO 拓扑排序 卡恩算法
 */

public class Main {
    public static void main(String[] args) throws IOException {

	    //AC的关键,得加速输入输出,因为这个卡了好久。。。。。。
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));

        String[] firstLine = in.readLine().split(" ");
        //输入点数
        int vNums = Integer.parseInt(firstLine[0]);
        //输入边数
        int eNums = Integer.parseInt(firstLine[1]);

        //用顺序表里面嵌套顺序表来代替图结构
        //嵌套的列表就相当于点,里面存储了它可达的下一个点
        ArrayList<ArrayList<Integer>> Graph = new ArrayList<>(vNums);

        //初始化点
        for (int i = 0; i < vNums; i++) {
            Graph.add(new ArrayList<>());
        }


        //输入边and//点的入度初始化
        int vb = 0;
        int ve = 0;
        int[] Infiltration = new
        int[vNums];//数组大小和点数量一致,一个点对应一个入度
        for (int i = 0; i < eNums; i++) {
            String[] edges = in.readLine().split(" ");
            //起始点
            vb = Integer.parseInt(edges[0]);
            //被指向点
            ve = Integer.parseInt(edges[1]);
            //因为列表索引0开始,点的数值1开始,通过vb-1来获取对应的点
            Graph.get(vb - 1).add(ve - 1);
            //对应的第i个ve点的入度+1
            Infiltration[ve - 1]++;
        }

        in.close();

        //初始化队列
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < vNums; i++) {
            //如果点的入度为0则入队
            if (Infiltration[i] == 0) {
                queue.add(i);
            }
        }


        //存储结果的列表
        ArrayList<Integer> result = new ArrayList<>();

        //统计点的个数看看存不存在环
        int countV = 0;
        //卡恩算法
        while (!queue.isEmpty()) {
            //出队元素加入结果列表同时点个数加一
            int cur = queue.poll();
            result.add(cur);
            countV++;
            //依次遍历出队点(入度为0的点)点对应的下一个点然后将其下一个点的入度-1
            for (int index : Graph.get(cur)) {
                if (--Infiltration[index] == 0) {
                    queue.add(index);
                }
            }
        }

        if (countV == vNums) {
            //出队
            for (int i = 0; i < result.size() - 1; i++) {
                //输出res+1是因为在
                // 初始化图列表时候应下标需要对应的点值都-1了
                // 然后包括添加到queue等一系列操作
                // 都是在操作对应下标现在需要打印了所以+1还原
                out.write(result.get(i) + 1 + " ");
            }
            //1 2 3 4 5
            // 复制样例过来看输出最后一个后面没有空格
            out.write((result.get(result.size() - 1) + 1) + "\n");
        } else {
            //最后一个输出没有空格
            String str = "-1";
            out.write(str);
        }
        out.close();
    }
}

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务