ACM HDOJ 2066 (一个人的旅行)

来源:互联网 发布:黑马程序员高清壁纸 编辑:程序博客网 时间:2024/04/30 02:11

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2066

思路 添加超级始点和超级终点,求超级始点到超级终点的最短路

程序一 dijkstra 算法

import java.util.Arrays;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int pointsNumber = 1002;int edgesNumber = Integer.parseInt(scn.next());int startNumber = Integer.parseInt(scn.next());int endNumber = Integer.parseInt(scn.next());Dijkstra dijkstra = new Dijkstra(pointsNumber);for (int i = 0; i < edgesNumber; ++i) {int start = Integer.parseInt(scn.next());int end = Integer.parseInt(scn.next());int distance = Integer.parseInt(scn.next());dijkstra.addEdge(start, end, distance);dijkstra.addEdge(end, start, distance);}int initStart = 0;int initEnd = 1001;for (int i = 0; i < startNumber; ++i) {int start = Integer.parseInt(scn.next());dijkstra.addEdge(initStart, start, 0);}for (int i = 0; i < endNumber; ++i) {int end = Integer.parseInt(scn.next());dijkstra.addEdge(end, initEnd, 0);}int distance = dijkstra.calculateDistance(initStart, initEnd);if (dijkstra.hasMinDistance()) {System.out.println(distance);} else {System.out.println("-1");}}scn.close();}}class Dijkstra {private final int INF = Integer.MAX_VALUE / 2;private int pointsNumber;private int[][] matrix;private boolean[] visit;private int[] resultDistance;private int resultMinDistance;public Dijkstra(int pointsNumber) {this.pointsNumber = pointsNumber;matrix = new int[pointsNumber][pointsNumber];for (int i = 0; i < pointsNumber; ++i) {Arrays.fill(matrix[i], INF);matrix[i][i] = 0;}visit = new boolean[pointsNumber];resultDistance = new int[pointsNumber];resultMinDistance = INF;}public void addEdge(int start, int end, int distance) {if (matrix[start][end] > distance) {matrix[start][end] = distance;}}public int calculateDistance(int initStart, int initEnd) {Arrays.fill(visit, false);visit[initStart] = true;for (int i = 0; i < pointsNumber; ++i) {resultDistance[i] = matrix[initStart][i];}for (int i = 0; i < pointsNumber; ++i) {int minDistance = INF;int minPoint = -1;for (int j = 0; j < pointsNumber; ++j) {if (!visit[j] && resultDistance[j] < minDistance) {minDistance = resultDistance[j];minPoint = j;}}if (-1 == minPoint || minPoint == initEnd) {break;}visit[minPoint] = true;for (int j = 0; j < pointsNumber; ++j) {if (!visit[j]&& resultDistance[j] - resultDistance[minPoint] > matrix[minPoint][j]) {resultDistance[j] = resultDistance[minPoint]+ matrix[minPoint][j];}}}resultMinDistance = resultDistance[initEnd];return resultDistance[initEnd];}public boolean hasMinDistance() {if (INF <= resultMinDistance) {return false;} else {return true;}}}

程序二 dijkstra 优先队列优化算法

import java.util.Arrays;import java.util.PriorityQueue;import java.util.Queue;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int pointsNumber = 1002;int edgesNumber = Integer.parseInt(scn.next());int startNumber = Integer.parseInt(scn.next());int endNumber = Integer.parseInt(scn.next());Dijkstra dijkstra = new Dijkstra(pointsNumber, edgesNumber * 2+ startNumber + endNumber);for (int i = 0; i < edgesNumber; ++i) {int start = Integer.parseInt(scn.next());int end = Integer.parseInt(scn.next());int distance = Integer.parseInt(scn.next());dijkstra.addEdge(start, end, distance);dijkstra.addEdge(end, start, distance);}int initStart = 0;int initEnd = 1001;for (int i = 0; i < startNumber; ++i) {int start = Integer.parseInt(scn.next());dijkstra.addEdge(initStart, start, 0);}for (int i = 0; i < endNumber; ++i) {int end = Integer.parseInt(scn.next());dijkstra.addEdge(end, initEnd, 0);}int distance = dijkstra.calculateDistance(initStart, initEnd);if (dijkstra.hasMinDistance()) {System.out.println(distance);} else {System.out.println("-1");}}scn.close();}}class Dijkstra {private final int INF = Integer.MAX_VALUE / 2;private int pointsNumber;private int edgesNumber;private int[] edgesDistance;private int[] edgesEnd;private int[] nextStart;private int[] startMax;private boolean[] visit;private int[] resultDistance;private int[] prePoint;private int resultMinDistance;public Dijkstra(int pointsNumber, int edgesNumber) {this.pointsNumber = pointsNumber;this.edgesNumber = 0;edgesDistance = new int[edgesNumber];edgesEnd = new int[edgesNumber];nextStart = new int[edgesNumber];startMax = new int[pointsNumber];Arrays.fill(startMax, -1);visit = new boolean[pointsNumber];resultDistance = new int[pointsNumber];prePoint = new int[pointsNumber];resultMinDistance = INF;}public void addEdge(int start, int end, int distance) {edgesDistance[edgesNumber] = distance;edgesEnd[edgesNumber] = end;nextStart[edgesNumber] = startMax[start];startMax[start] = edgesNumber++;}public int calculateDistance(int initStart, int initEnd) {Arrays.fill(visit, false);Arrays.fill(resultDistance, INF);Arrays.fill(prePoint, -1);visit[initStart] = true;resultDistance[initStart] = 0;int currentPoint = initStart;Queue<Node> queue = new PriorityQueue<Node>();for (int i = 1; i < pointsNumber; ++i) {for (int j = startMax[currentPoint]; j != -1; j = nextStart[j]) {int k = edgesEnd[j];if (!visit[k]&& resultDistance[currentPoint] < resultDistance[k]- edgesDistance[j]) {resultDistance[k] = resultDistance[currentPoint]+ edgesDistance[j];queue.offer(new Node(k, resultDistance[k]));prePoint[k] = currentPoint;}}while (!queue.isEmpty()) {Node node = queue.peek();if (visit[node.getPoint()]) {queue.poll();} else {break;}}if (queue.isEmpty()) {break;}currentPoint = queue.poll().getPoint();visit[currentPoint] = true;if (currentPoint == initEnd) {break;}}resultMinDistance = resultDistance[initEnd];return resultDistance[initEnd];}public boolean hasMinDistance() {if (INF <= resultMinDistance) {return false;} else {return true;}}}class Node implements Comparable<Node> {private int point;private int distance;public Node(int point, int distance) {this.point = point;this.distance = distance;}public int getPoint() {return point;}public int getDistance() {return distance;}@Overridepublic int compareTo(Node node) {if (this.distance > node.distance) {return 1;} else if (this.distance < node.distance) {return -1;} else {return this.point - node.point;}}}
程序三 bellman-ford 算法

import java.util.Arrays;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int pointsNumber = 1002;int edgesNumber = Integer.parseInt(scn.next());int startNumber = Integer.parseInt(scn.next());int endNumber = Integer.parseInt(scn.next());BellmanFord bellmanFord = new BellmanFord(pointsNumber, edgesNumber* 2 + startNumber + endNumber);for (int i = 0; i < edgesNumber; ++i) {int start = Integer.parseInt(scn.next());int end = Integer.parseInt(scn.next());int distance = Integer.parseInt(scn.next());bellmanFord.addEdge(start, end, distance);bellmanFord.addEdge(end, start, distance);}int initStart = 0;int initEnd = 1001;for (int i = 0; i < startNumber; ++i) {int start = Integer.parseInt(scn.next());bellmanFord.addEdge(initStart, start, 0);}for (int i = 0; i < endNumber; ++i) {int end = Integer.parseInt(scn.next());bellmanFord.addEdge(end, initEnd, 0);}int distance = bellmanFord.calculateDistance(initStart, initEnd);if (bellmanFord.hasMinDistance()) {System.out.println(distance);} else {System.out.println("-1");}}scn.close();}}class BellmanFord {private final int INF = Integer.MAX_VALUE / 2;private int pointsNumber;private int edgesNumber;private Edge[] edge;private int[] resultDistance;private int[] prePoint;private int resultMinDistance;private boolean relax(int start, int end, int distance) {if (resultDistance[end] - distance > resultDistance[start]) {resultDistance[end] = resultDistance[start] + distance;prePoint[end] = start;return true;} else {return false;}}public BellmanFord(int pointsNumber, int edgesNumber) {this.pointsNumber = pointsNumber;this.edgesNumber = 0;edge = new Edge[edgesNumber];resultDistance = new int[pointsNumber];prePoint = new int[pointsNumber];resultMinDistance = INF;}public void addEdge(int start, int end, int distance) {edge[edgesNumber++] = new Edge(start, end, distance);}public int calculateDistance(int initStart, int initEnd) {Arrays.fill(resultDistance, INF);Arrays.fill(prePoint, -1);resultDistance[initStart] = 0;for (int i = 1; i < pointsNumber; ++i) {Boolean flag = false;for (int j = 0; j < edgesNumber; ++j) {if (relax(edge[j].getStart(), edge[j].getEnd(),edge[j].getDistance())) {flag = true;}}if (!flag) {break;}}for (int i = 0; i < edgesNumber; ++i) {if (relax(edge[i].getStart(), edge[i].getEnd(),edge[i].getDistance())) {resultMinDistance = -INF;return -INF;}}resultMinDistance = resultDistance[initEnd];return resultDistance[initEnd];}public boolean hasMinDistance() {if (hasNegativeRing() || INF <= resultMinDistance) {return false;} else {return true;}}public boolean hasNegativeRing() {if (-INF >= resultMinDistance) {return true;} else {return false;}}}class Edge {private int start;private int end;private int distance;public Edge(int start, int end, int distance) {this.start = start;this.end = end;this.distance = distance;}public int getStart() {return start;}public int getEnd() {return end;}public int getDistance() {return distance;}}

程序四 spfa 算法

import java.util.Arrays;import java.util.LinkedList;import java.util.Queue;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int pointsNumber = 1002;int edgesNumber = Integer.parseInt(scn.next());int startNumber = Integer.parseInt(scn.next());int endNumber = Integer.parseInt(scn.next());Spfa spfa = new Spfa(pointsNumber, edgesNumber * 2 + startNumber+ endNumber);for (int i = 0; i < edgesNumber; ++i) {int start = Integer.parseInt(scn.next());int end = Integer.parseInt(scn.next());int distance = Integer.parseInt(scn.next());spfa.addEdge(start, end, distance);spfa.addEdge(end, start, distance);}int initStart = 0;int initEnd = 1001;for (int i = 0; i < startNumber; ++i) {int start = Integer.parseInt(scn.next());spfa.addEdge(initStart, start, 0);}for (int i = 0; i < endNumber; ++i) {int end = Integer.parseInt(scn.next());spfa.addEdge(end, initEnd, 0);}int distance = spfa.calculateDistance(initStart, initEnd);if (spfa.hasMinDistance()) {System.out.println(distance);} else {System.out.println("-1");}}scn.close();}}class Spfa {private final int INF = Integer.MAX_VALUE / 2;private int pointsNumber;private int edgesNumber;private int[] edgesDistance;private int[] edgesEnd;private int[] nextStart;private int[] startMax;private boolean[] visit;private int[] resultDistance;private int[] prePoint;private int[] count;private int resultMinDistance;private boolean relax(int start, int end, int distance) {if (resultDistance[end] - distance > resultDistance[start]) {resultDistance[end] = resultDistance[start] + distance;prePoint[end] = start;return true;} else {return false;}}public Spfa(int pointsNumber, int edgesNumber) {this.pointsNumber = pointsNumber;this.edgesNumber = 0;edgesDistance = new int[edgesNumber];edgesEnd = new int[edgesNumber];nextStart = new int[edgesNumber];startMax = new int[pointsNumber];Arrays.fill(startMax, -1);visit = new boolean[pointsNumber];resultDistance = new int[pointsNumber];prePoint = new int[pointsNumber];count = new int[pointsNumber];resultMinDistance = INF;}public void addEdge(int start, int end, int distance) {edgesDistance[edgesNumber] = distance;edgesEnd[edgesNumber] = end;nextStart[edgesNumber] = startMax[start];startMax[start] = edgesNumber++;}public int calculateDistance(int initStart, int initEnd) {Arrays.fill(visit, false);Arrays.fill(resultDistance, INF);Arrays.fill(prePoint, -1);Arrays.fill(count, 0);visit[initStart] = true;resultDistance[initStart] = 0;++count[initStart];Queue<Integer> queue = new LinkedList<Integer>();queue.offer(initStart);while (!queue.isEmpty()) {int start = queue.poll();visit[start] = false;for (int i = startMax[start]; i != -1; i = nextStart[i]) {int end = edgesEnd[i];if (relax(start, end, edgesDistance[i]) && !visit[end]) {queue.offer(end);visit[end] = true;if ((++count[end]) > pointsNumber) {resultMinDistance = -INF;return -INF;}}}}resultMinDistance = resultDistance[initEnd];return resultDistance[initEnd];}public boolean hasMinDistance() {if (hasNegativeRing() || INF <= resultMinDistance) {return false;} else {return true;}}public boolean hasNegativeRing() {if (-INF >= resultMinDistance) {return true;} else {return false;}}}

0 0