您的位置:首页 > 编程语言 > Java开发

ACM HDOJ 2066 (一个人的旅行)

2014-01-17 23:03 309 查看
题目链接 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;
}

@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 = 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 calculateDistan
b923
ce(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;
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM HDOJ 2066 JAVA