All Downloads are FREE. Search and download functionalities are using the official Maven repository.

shz.ShortestPath Maven / Gradle / Ivy

package shz;

import shz.msg.ServerFailureMsg;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class ShortestPath {
    protected static class Node {
        public String name;
        public Integer weight;

        public Node(String name) {
            this.name = name;
        }
    }

    protected Node node;
    protected Map nodes;
    protected ShortestPath prev;

    protected ShortestPath(String name, int size) {
        this.node = new Node(name);
        this.nodes = ToMap.get(size).build();
    }

    public final ShortestPath add(ShortestPath optimal, int weight) {
        nodes.put(optimal, weight);
        return this;
    }

    public static final class Result {
        int sum;
        List ways;

        Result(int sum, List ways) {
            this.sum = sum;
            this.ways = ways;
        }

        public int sum() {
            return sum;
        }

        public List ways() {
            return ways;
        }

        @Override
        public String toString() {
            return "Result{" +
                    "sum=" + sum +
                    ", ways=" + ways +
                    '}';
        }
    }

    public final Result go(ShortestPath des) {
        node.weight = 0;
        update();
        TreeMap treeMap = new TreeMap<>((t, u) -> u - t);
        int count = 0;
        treeMap.put(count++, des.node.name);
        ShortestPath optimal = des;
        while ((optimal = optimal.prev) != null) treeMap.put(count++, optimal.node.name);
        Result result = new Result(des.node.weight, new ArrayList<>(treeMap.values()));
        reset();
        return result;
    }

    protected abstract void update();

    public final void reset() {
        Queue queue = new LinkedList<>();
        Set book = new HashSet<>();
        queue.offer(this);
        while (!queue.isEmpty()) {
            ShortestPath poll = queue.poll();
            poll.node.weight = null;
            poll.prev = null;
            book.add(poll.node.name);
            poll.nodes.forEach((k, v) -> {
                if (!book.contains(k.node.name)) queue.offer(k);
            });
        }
    }

    public static final class BellmanFord extends ShortestPath {
        public BellmanFord(String name, int size) {
            super(name, size);
        }

        @Override
        protected void update() {
            Queue queue = new LinkedList<>();
            Set book = new HashSet<>();
            AtomicInteger atomic = new AtomicInteger();
            update0(queue, book, atomic);
            int sum = 0, count = 0;
            while (sum != (sum = atomic.get()) && count++ < book.size()) {
                atomic.set(0);
                book.clear();
                update0(queue, book, atomic);
            }
            ServerFailureMsg.requireNon(count >= book.size(), "无法确定最优方案");
        }

        private void update0(Queue queue, Set book, AtomicInteger atomic) {
            queue.offer(this);
            while (!queue.isEmpty()) {
                ShortestPath poll = queue.poll();
                book.add(poll.node.name);
                poll.nodes.forEach((k, v) -> {
                    int weight = poll.node.weight + v;
                    if (k.node.weight == null || weight < k.node.weight) {
                        k.node.weight = weight;
                        k.prev = poll;
                    }
                    weight = k.node.weight + v;
                    if (weight < poll.node.weight) {
                        poll.node.weight = weight;
                        poll.prev = k;
                    }
                    if (!book.contains(k.node.name)) queue.offer(k);
                });
                atomic.addAndGet(poll.node.weight);
            }
        }
    }

    public static final class Dijkstra extends ShortestPath {
        public Dijkstra(String name, int size) {
            super(name, size);
        }

        @Override
        protected void update() {
            PQueue queue = PQueue.of(Comparator.comparingInt(t -> t.node.weight));
            Set book = new HashSet<>();
            queue.offer(this);
            while (!queue.isEmpty()) {
                ShortestPath poll = queue.poll();
                if (poll == null) continue;
                book.add(poll.node.name);
                poll.nodes.forEach((k, v) -> {
                    int weight = poll.node.weight + v;
                    if (k.node.weight == null || weight < k.node.weight) {
                        k.node.weight = weight;
                        k.prev = poll;
                    }
                    if (!book.contains(k.node.name)) queue.offer(k);
                });
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy