Dijkstra-单源最短路径-java实现

问题描述

求从 开始的所有点的最短路径的长度s。点 id 是从 1, 2, ... 到 N。

输入

  • N, M, S
  • 后面是 M 行,每一行是u v w,代表一条从u到到v长度为 的路径w

输出

  • N行,每一行是s到第i个点的距离。如果无法到达,则目的地为 -1。

  • 尺寸

  • N <= 1,000,000
  • M <= 2,000,000
  • w >= 0
  • 总长度以 为界int32_t
难点:
时间限制:  1.5s
内存限制: 200M

为了保证空间复杂度,这里选用List<Node>[]来存储图的信息,其中node节点记录pos位置和cost目标点到pos位置的花费,数据的读取采用BufferedReader而不是Scanner,亲测,效率更高;将数据存储好之后采用Dijkstra算法(参考百度百科)求得目标点到其余每个点的最短距离。代码如下:

public class Temp {

    static int[] dist = new int[1000000];

    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        int num[] = toInteger(bufferedReader.readLine());
        int N = num[0],M=num[1],S=num[2];
        List<Node>[] list = new ArrayList[N];
        for (int i=0;i<N;i++){
            list[i] = new ArrayList<>();
        }
        Arrays.fill(dist,0,N,-1);
        while (M>0){
            num = toInteger(bufferedReader.readLine());
            int start = num[0] -1,end = num[1] - 1,length = num[2];
            Node node = new Node(end,length);
            List<Node> map =  list[start];
            map.add(node);
            --M;
        }
        Dijkstra(S - 1,  list, new int[N]);
        for (int i=0;i<list.length;i++) {
//            int res = Dijkstra(S - 1, i, list, new int[N]);
            System.out.println(dist[i]);
        }
    }

//visit[i] == 0,代表未访问,visit[0] == -1代表已访问
    public static int Dijkstra(int src, List<Node>[] graph, int[] visit){
        PriorityQueue<Node> pq = new PriorityQueue<>(new Node());
        //将起点加入pq
        pq.add(new Node(src, 0));
        while (!pq.isEmpty()){
            Node t = pq.poll();
            if (dist[t.node] > t.cost || dist[t.node] < 0) {
                dist[t.node] = t.cost;
            }
            //t节点表示还未访问
            if (visit[t.node]==0){
                //将节点设置为已访问
                visit[t.node] = -1;
                //将当前节点相连且未访问的节点遍历
                 List<Node> nodes = graph[t.node];
                for (Node k : nodes){
                    if (visit[k.node] == 0 ){
                        k.setCost(k.getCost()+t.cost);
                        pq.add(k);
                    }
                }
            }
        }
        return -1;
    }

    //定义一个存储节点和离起点相应距离的数据结构
    static class Node implements Comparator<Node> {
        public int node;
        public int cost;

        public Node(){}

        public Node(int node, int cost){
            this.node = node;
            this.cost = cost;
        }

        public int getNode() {
            return node;
        }

        public void setNode(int node) {
            this.node = node;
        }

        public int getCost() {
            return cost;
        }

        public void setCost(int cost) {
            this.cost = cost;
        }

        @Override
        public int compare(Node node1, Node node2){
            return node1.cost-node2.cost;
        }
    }


    private static int[] toInteger(String srt) {
        int i = 0;
        int a1 = 0;
        int a2 = 0;
        int a3 = 0;

        while (srt.charAt(i)!=' ') {
            a1 = a1 * 10 + (srt.charAt(i) - '0');
            i++;
        }
        i++;

        while (srt.charAt(i)!=' ') {
            a2 = a2 * 10 + (srt.charAt(i) - '0');
            i++;
        }
        i++;

        while (i != srt.length()) {
            a3 = a3 * 10 + (srt.charAt(i) - '0');
            i++;
        }
        int[] list = new int[3];
        list[0] = a1;
        list[1] = a2;
        list[2] = a3;
        return list;
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值