ACM HDOJ 2544 (最短路)

24 篇文章 0 订阅
8 篇文章 0 订阅

题目链接 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];
	}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值