题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2544
程序一 floyd 算法
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 = Integer.parseInt(scn.next());
int edgesNumber = Integer.parseInt(scn.next());
if (0 == pointsNumber && 0 == edgesNumber) {
break;
}
Floyd floyd = new Floyd(pointsNumber);
for (int i = 0; i < edgesNumber; ++i) {
int start = Integer.parseInt(scn.next()) - 1;
int end = Integer.parseInt(scn.next()) - 1;
int distance = Integer.parseInt(scn.next());
floyd.addEdge(start, end, distance);
floyd.addEdge(end, start, distance);
}
floyd.calculateDistance();
int initStart = 0;
int initEnd = pointsNumber - 1;
int distance = floyd.getMatrixItem(initStart, initEnd);
System.out.println(distance);
}
scn.close();
}
}
class Floyd {
private final int INF = Integer.MAX_VALUE / 2;
private int pointsNumber;
private int[][] matrix;
public Floyd(int pointsNumber) {
this.pointsNumber = pointsNumber;
this.matrix = new int[pointsNumber][pointsNumber];
for (int i = 0; i < pointsNumber; ++i) {
Arrays.fill(matrix[i], INF);
matrix[i][i] = 0;
}
}
public void addEdge(int start, int end, int distance) {
if (matrix[start][end] > distance) {
matrix[start][end] = distance;
}
}
public void calculateDistance() {
for (int k = 0; k < pointsNumber; ++k) {
for (int i = 0; i < pointsNumber; ++i) {
for (int j = 0; j < pointsNumber; ++j) {
if (matrix[i][j] - matrix[i][k] > matrix[k][j]) {
matrix[i][j] = matrix[i][k] + matrix[k][j];
}
}
}
}
}
public int getMatrixItem(int start, int end) {
return matrix[start][end];
}
}
程序二 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 = Integer.parseInt(scn.next());
int edgesNumber = Integer.parseInt(scn.next());
if (0 == pointsNumber && 0 == edgesNumber) {
break;
}
Dijkstra dijkstra = new Dijkstra(pointsNumber);
for (int i = 0; i < edgesNumber; ++i) {
int start = Integer.parseInt(scn.next()) - 1;
int end = Integer.parseInt(scn.next()) - 1;
int distance = Integer.parseInt(scn.next());
dijkstra.addEdge(start, end, distance);
dijkstra.addEdge(end, start, distance);
}
int initStart = 0;
int initEnd = pointsNumber - 1;
int distance = dijkstra.calculateDistance(initStart, initEnd);
System.out.println(distance);
}
scn.close();
}
}
class Dijkstra {
private final int INF = Integer.MAX_VALUE / 2;
private int pointsNumber;
private int[][] matrix;
private boolean[] visit;
private int[] resultDistance;
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];
}
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];
}
}
}
return resultDistance[initEnd];
}
}
程序三 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 = Integer.parseInt(scn.next());
int edgesNumber = Integer.parseInt(scn.next());
if (0 == pointsNumber && 0 == edgesNumber) {
break;
}
Dijkstra dijkstra = new Dijkstra(pointsNumber, edgesNumber * 2);
for (int i = 0; i < edgesNumber; ++i) {
int start = Integer.parseInt(scn.next()) - 1;
int end = Integer.parseInt(scn.next()) - 1;
int distance = Integer.parseInt(scn.next());
dijkstra.addEdge(start, end, distance);
dijkstra.addEdge(end, start, distance);
}
int initStart = 0;
int initEnd = pointsNumber - 1;
int distance = dijkstra.calculateDistance(initStart, initEnd);
System.out.println(distance);
}
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;
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];
}
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;
}
}
return resultDistance[initEnd];
}
}
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;
}
@Override
public 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 = Integer.parseInt(scn.next());
int edgesNumber = Integer.parseInt(scn.next());
if (0 == pointsNumber && 0 == edgesNumber) {
break;
}
BellmanFord bellmanFord = new BellmanFord(pointsNumber,
edgesNumber * 2);
for (int i = 0; i < edgesNumber; ++i) {
int start = Integer.parseInt(scn.next()) - 1;
int end = Integer.parseInt(scn.next()) - 1;
int distance = Integer.parseInt(scn.next());
bellmanFord.addEdge(start, end, distance);
bellmanFord.addEdge(end, start, distance);
}
int initStart = 0;
int initEnd = pointsNumber - 1;
int distance = bellmanFord.calculateDistance(initStart, initEnd);
System.out.println(distance);
}
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 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];
}
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())) {
return -INF;
}
}
return resultDistance[initEnd];
}
}
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 = Integer.parseInt(scn.next());
int edgesNumber = Integer.parseInt(scn.next());
if (0 == pointsNumber && 0 == edgesNumber) {
break;
}
Spfa spfa = new Spfa(pointsNumber, edgesNumber * 2);
for (int i = 0; i < edgesNumber; ++i) {
int start = Integer.parseInt(scn.next()) - 1;
int end = Integer.parseInt(scn.next()) - 1;
int distance = Integer.parseInt(scn.next());
spfa.addEdge(start, end, distance);
spfa.addEdge(end, start, distance);
}
int initStart = 0;
int initEnd = pointsNumber - 1;
int distance = spfa.calculateDistance(initStart, initEnd);
System.out.println(distance);
}
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 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];
}
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) {
return -INF;
}
}
}
}
return resultDistance[initEnd];
}
}