Hdu1874-畅通工程续(最短路dijkstra和堆优化)

Hdu1874-畅通工程续(最短路dijkstra和堆优化)

  • dijkstra算法总结
  • 普通dijstra算法解决
  • 堆优化解决
  • 手写堆解决

题目链接

dijkstra算法总结

总结一下dijkstra算法大致的流程:

  • 一开始有一个dist[]数组(也可以是map)来保存从start(起点)到每个点的最短路径(一开始的话,如果start和某个点没有边,就为INF(或者为null),如果有连线的话就是边的权值);
  • 然后从dist数组中取出一个dist[i]最小的i,也就是start距离某个结点最近的一个;
  • 取出这个结点之后,用这个结点更新和它相连的边的dist数组
  • 直到把所有的dist数组都更新一遍;

本来也想自己画一个图的,看到网上有一个很好的,感觉自己再写也没他讲的清楚。

一个讲的好的博客


普通dijstra算法解决

import java.io.BufferedInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Scanner;

public class Main {

    private static class Node{
        public int value;
        public ArrayList<Edge>edges;

        public Node(int value) {
            this.value = value;
            edges = new ArrayList<>();
        }
    }

    private static class Edge{
        public int weight;
        public Node from;
        public Node to;

        public Edge( Node from, Node to,int weight) {
            this.from = from;
            this.to = to;
            this.weight = weight;
        }
    }

    private static class Graph{
        public HashMap<Integer,Node>nodes;

        public Graph() {
            nodes = new HashMap<>();
        }
    }

    //没有使用堆优化的 O(n^2)
    public static HashMap<Node,Integer> dijkstra(Node head){
        HashMap<Node,Integer>dist = new HashMap<>();
        dist.put(head,0);
        for(Edge edge : head.edges){
            dist.put(edge.to,edge.weight);
        }

        HashSet<Node>set = new HashSet<>();
        for(Node minNode = getMinAndUnSelect(dist,set); minNode != null ; minNode = getMinAndUnSelect(dist,set)){
            int distance = dist.get(minNode);
            for(Edge edge : minNode.edges){
                Node toNode = edge.to;
                if(set.contains(toNode))continue;
                if(!dist.containsKey(toNode)){
                    dist.put(toNode,distance + edge.weight);
                }
                dist.put(toNode,Math.min(dist.get(toNode),distance + edge.weight));
            }
            set.add(minNode); //使用过这个之后就标记
        }
        return dist;
    }

    //找出dist中最小且没有选择的结点
    private static Node getMinAndUnSelect(HashMap<Node, Integer> dist, HashSet<Node> set) {
        Node minNode = null;
        int minDistance = Integer.MAX_VALUE;
        for(Entry<Node,Integer> entry : dist.entrySet()){ // map遍历方式 https://www.cnblogs.com/fqfanqi/p/6187085.html
            Node node = entry.getKey();
            int distance = entry.getValue();
            if(!set.contains(node) && distance < minDistance){
                minDistance = distance;
                minNode = node;
            }
        }
        return minNode;
    }


    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        while(cin.hasNext()){
            int n = cin.nextInt();
            int m = cin.nextInt();
            Graph G = new Graph();
            for(int i = 0; i < n; i++)G.nodes.put(i,new Node(i));
            for(int i = 0; i < m; i++){
                int a = cin.nextInt();
                int b = cin.nextInt();
                int w = cin.nextInt();
                Node from = G.nodes.get(a);
                Node to = G.nodes.get(b);
                from.edges.add(new Edge(from,to,w));
                to.edges.add(new Edge(to,from,w));
            }
            int start = cin.nextInt();
            int end = cin.nextInt();
            HashMap<Node, Integer> dist = dijkstra(G.nodes.get(start));//从start开始
            Integer res = dist.get(G.nodes.get(end));
            System.out.println((res == null) ? -1 : res);
        }
    }
}

堆优化解决

import java.io.BufferedInputStream;
import java.util.*;
import java.util.Map.Entry;

public class Main {

    private static class Node{
        public int value;
        public ArrayList<Edge>edges;

        public Node(int value) {
            this.value = value;
            edges = new ArrayList<>();
        }
    }

    private static class Edge{
        public int weight;
        public Node from;
        public Node to;

        public Edge( Node from, Node to,int weight) {
            this.from = from;
            this.to = to;
            this.weight = weight;
        }
    }

    private static class Graph{
        public HashMap<Integer,Node>nodes;

        public Graph() {
            nodes = new HashMap<>();
        }
    }

    private static class NodeRecord {
        public Node node;
        public int distance;

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

    private static class EdgeComparator implements Comparator<NodeRecord>{

        @Override
        public int compare(NodeRecord o1, NodeRecord o2) {
            return o1.distance - o2.distance;
        }
    }

    public static HashMap<Node, Integer> dijkstra(Node head){
        HashMap<Node,Integer>dist = new HashMap<>();
        dist.put(head,0);
        for(Edge edge : head.edges){//这个不能少
            dist.put(edge.to,edge.weight);
        }
        PriorityQueue<NodeRecord>priorityQueue = new PriorityQueue<>(new EdgeComparator());
        priorityQueue.add(new NodeRecord(head,0));
        HashSet<Node>set = new HashSet<>();
        while(!priorityQueue.isEmpty()){
            NodeRecord poll = priorityQueue.poll();
            Node cur = poll.node;
            int distance = poll.distance;
            if(set.contains(cur))continue;
            set.add(cur);
            for(Edge edge : cur.edges){
                int w = edge.weight;
                Node toNode = edge.to;
                if(set.contains(toNode))continue;
                if(!dist.containsKey(toNode))dist.put(toNode,distance + w);
                dist.put(toNode,Math.min(dist.get(toNode),distance + w));
                priorityQueue.add(new NodeRecord(toNode,dist.get(toNode)));
            }
        }
        return dist;
    }


    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        while(cin.hasNext()){
            int n = cin.nextInt();
            int m = cin.nextInt();
            Graph G = new Graph();
            for(int i = 0; i < n; i++)G.nodes.put(i,new Node(i));
            for(int i = 0; i < m; i++){
                int a = cin.nextInt();
                int b = cin.nextInt();
                int w = cin.nextInt();
                Node from = G.nodes.get(a);
                Node to = G.nodes.get(b);
                from.edges.add(new Edge(from,to,w));
                to.edges.add(new Edge(to,from,w)); //注意无向图
            }
            int start = cin.nextInt();
            int end = cin.nextInt();
            HashMap<Node, Integer> dist = dijkstra(G.nodes.get(start));//从start开始
            Integer res = dist.get(G.nodes.get(end));
            System.out.println((res == null) ? -1 : res);
        }
    }
}

手写堆解决

import java.io.BufferedInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

public class Main {
    private static class Node{
        public int value;
        public ArrayList<Edge> edges;

        public Node(int value) {
            this.value = value;
            edges = new ArrayList<>();
        }
    }

    private static class Edge{
        public int weight;
        public Node from;
        public Node to;

        public Edge( Node from, Node to,int weight) {
            this.from = from;
            this.to = to;
            this.weight = weight;
        }
    }

    private static class Graph{
        public HashMap<Integer,Node> nodes;

        public Graph() {
            nodes = new HashMap<>();
        }
    }

    private static class NodeRecord {
        public Node node;
        public int distance;

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

    private static class NodeHeap {
        private Node[] nodes;
        private HashMap<Node, Integer> indexMap;//堆的下标
        private HashMap<Node, Integer> distMap; //堆里面Node对应的distance
        private int size;

        public NodeHeap(int size) {
            nodes = new Node[size];
            indexMap = new HashMap<>();
            distMap = new HashMap<>();
            this.size = 0;
        }

        public boolean isEmpty() {//堆是否为空
            return size == 0;
        }

        public void addOrUpdateOrIgnore(Node node, int distance) {
            //如果在堆中已经有了这个结点,就要更新   -1表示的是被访问过了
            if (indexMap.containsKey(node) && indexMap.get(node) != -1) { //update contain and index != -1
                distMap.put(node, Math.min(distMap.get(node), distance));
                insertHeapify(node, indexMap.get(node));
            }

            //如果 堆中没有这个结点 就创建一个
            if (!indexMap.containsKey(node)) {//if isEntered --> ignore
                nodes[size] = node;
                indexMap.put(node, size);
                distMap.put(node, distance);
                insertHeapify(node, size++);
            }
        }

        //从堆中取一个
        public NodeRecord poll() {
            NodeRecord top = new NodeRecord(nodes[0], distMap.get(nodes[0]));//取出堆顶
            swap(0, size - 1); //和最后一个交换
            indexMap.put(nodes[size - 1], -1); //标记已经用过,相当于 Hashset作用
            distMap.remove(nodes[size - 1]);  //距离数组中李处
            nodes[size - 1] = null;  //结点数组中设置为null
            heapify(0, --size);
            return top;
        }

        private void insertHeapify(Node node, int index) { //插入并调整
            while (distMap.get(nodes[index]) < distMap.get(nodes[(index - 1) / 2])) {
                swap(index, (index - 1) / 2);
                index = (index - 1) / 2;
            }
        }

        private void heapify(int index, int size) {
            int left = index * 2 + 1;
            while (left < size) {
                int minIndex = left + 1 < size && distMap.get(nodes[left + 1]) < distMap.get(nodes[left])
                        ? left + 1 : left;
                minIndex = distMap.get(nodes[minIndex]) < distMap.get(nodes[index]) ? minIndex : index;
                if (minIndex == index) break;
                swap(minIndex, index);
                index = minIndex;
                left = index * 2 + 1;
            }
        }

        private void swap(int a, int b) {
            indexMap.put(nodes[a], b);//交换各自的下标
            indexMap.put(nodes[b], a);
            Node tmp = nodes[a];
            nodes[a] = nodes[b];
            nodes[b] = tmp;
        }
    }

    private static HashMap<Node,Integer> dijkstra(Graph G,int start){
        NodeHeap heap = new NodeHeap(G.nodes.size());
        heap.addOrUpdateOrIgnore(G.nodes.get(start),0);
        HashMap<Node,Integer>dist = new HashMap<>();
        while(!heap.isEmpty()){
            NodeRecord poll = heap.poll();
            Node cur = poll.node;
            int distance = poll.distance;
            for(Edge edge : cur.edges){
                heap.addOrUpdateOrIgnore(edge.to, distance + edge.weight);
            }
            dist.put(cur,distance);
        }
        return dist;
    }


    private static Graph createGraph(Scanner cin,int n,int m){
        Graph G = new Graph();
        for(int i = 0; i < n; i++)G.nodes.put(i,new Node(i));
        for(int i = 0; i < m; i++){
            int a = cin.nextInt();
            int b = cin.nextInt();
            int w = cin.nextInt();
            Node from = G.nodes.get(a);
            Node to = G.nodes.get(b);
            from.edges.add(new Edge(from,to,w));
            to.edges.add(new Edge(to,from,w));
        }
        return G;
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        while(cin.hasNext()){
            int n = cin.nextInt();
            int m = cin.nextInt();
            Graph G = createGraph(cin,n,m);
            int start = cin.nextInt();
            int end = cin.nextInt();
            HashMap<Node, Integer> dist = dijkstra(G,start);//从start开始
            Integer res = dist.get(G.nodes.get(end));
            System.out.println((res == null) ? -1 : res);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/zxzxzx0119/article/details/81561440