【题目】Problem C.城市道路(迪杰斯特拉、弗洛伊德解法)

Problem C 城市道路

题目描述
n个城市之间有若干道路,其中某些道路黑夜需要关闭,分别求出城市1到城市n白天和黑夜的最短路径。

输入格式
第一行为数据组数T

对于每组测试数据

第一行三个整数,n,m,k. (1<=n<=50)n表示城市个数,m表示道路个数,k表示黑夜需要关闭的道路个数。

接下来m行,每行 三个整数 a,b,c (1<=a,b<=n),其中第 i 行(1<=i <=m)表示第 i 条道路为从城市a到城市b长度为c(可能存在重复边)。

接下来k行,每行一个整数w,表示黑夜要关闭的道路编号。

输出格式
每组数据输出两行

第一行为白天从城市1到城市n的最短距离
第一行为黑夜从城市1到城市n的最短距离

输入样例

1
4 4 1
1 2 1
2 3 1
3 4 1
1 4 1
4

输出样例

1
3

解答:(Dijkstra算法)

import java.util.Arrays;
import java.util.Scanner;

/*
Problem C 最短路径
题目
计算从城市1到城市n的最短路径长度。分为白天和黑夜,黑夜会关掉若干条线路,分别计算城市1到城市n的在白天和黑夜的最短路径长度。保证每个城市与其他城市必有连接。两个城市之间可能有多重边
输入
第一行输入T,测试用例组数
第二行输入n,m,k. n是城市数,m是边数,k是黑夜关闭的边数(n<=50)
接下来m行,每行输入三个数x,y,z,代表城市x和城市y之间的距离
最后一行k个数,代表晚上关闭的线路序号
输出
每组数据输出两行,分别代表白天和黑夜,城市1到n的最短路径长度
测试用例
输入
1
4 4 1
1 2 1
2 3 1
3 4 1
1 4 1
4
输出
1
3
*/
public class Test{
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		while(scanner.hasNext()) {
			int number = scanner.nextInt();
			for(int i = 0; i < number; i++) {
				int c = scanner.nextInt();
				int v = scanner.nextInt();
				int nv = scanner.nextInt();
				int[] night = new int[nv];
				int[][] num = new int[c][c];
				int[][] graph = new int[v][3];
				for(int j = 0; j < v; j++) {
					graph[j][0] = scanner.nextInt() - 1;
					graph[j][1] = scanner.nextInt() - 1;
					graph[j][2] = scanner.nextInt();
				}
				for(int j = 0; j < nv; j++) night[j] = scanner.nextInt() - 1;
				for(int j = 0; j < c; j++) num[graph[j][1]][graph[j][0]] = num[graph[j][0]][graph[j][1]] = graph[j][2]; //初始化图 - 白天的图
				int value = Dijkstra(num, 1, c);
				System.out.println(value);
				//黑夜后
				int l = 0;
				num = new int[c][c];
				for(int j = 0; j < c; j++) //初始化图 - 黑夜时重新建图(因为有多重边)
					if(j == night[l]) {
						l++;
						continue;
					}else num[graph[j][1]][graph[j][0]] = num[graph[j][0]][graph[j][1]] = graph[j][2];
				for(int j = 0; j < c; j++)
				value = Dijkstra(num, 1, c);
				System.out.println(value);
			}
		}
	}
	
	public static int Dijkstra(int[][] nums, int s, int n) {//s起点,n为终点
		int[] d = new int[nums.length];//起点到各点的距离长度
		boolean[] visit = new boolean[nums.length];//是否访问过
		Arrays.fill(d, Integer.MAX_VALUE);//填满距离数组,都为最大值
		d[s - 1] = 0;//起点到起点距离为0
		for(int i = 0; i < nums.length; i++) {
			int u = -1, min = Integer.MAX_VALUE;//d[u]最小,min中存放该最小的d[u]
			for(int j = 0; j < nums.length; j ++) //起点到所有节点一趟中的最小值
				if(visit[j] == false && d[j] < min) {
					u = j;
					min = d[j];
				}
			if(u == -1) return 0;//找不到小于min的d[u],说明剩下的顶点和起点s不连通
			visit[u] = true;//赋值给起点到u
			for(int v = 0; v < nums.length; v++) 
				if(visit[v] == false && nums[u][v] != 0 && d[u] + nums[u][v] < d[v]) //v未访问 && u能到v && 以u为中介可以使d[v]更优
					d[v] = d[u] + nums[u][v];
		}
		return d[n - 1];
	}
}

解答:(Floyd算法)

import java.util.Scanner;

/*
Problem C 最短路径
题目
计算从城市1到城市n的最短路径长度。分为白天和黑夜,黑夜会关掉若干条线路,分别计算城市1到城市n的在白天和黑夜的最短路径长度。保证每个城市与其他城市必有连接。两个城市之间可能有多重边
输入
第一行输入T,测试用例组数
第二行输入n,m,k. n是城市数,m是边数,k是黑夜关闭的边数(n<=50)
接下来m行,每行输入三个数x,y,z,代表城市x和城市y之间的距离
最后一行k个数,代表晚上关闭的线路序号
输出
每组数据输出两行,分别代表白天和黑夜,城市1到n的最短路径长度
测试用例
输入
1
4 4 1
1 2 1
2 3 1
3 4 1
1 4 1
4
输出
1
3
*/
public class Test{
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		while(scanner.hasNext()) {
			int number = scanner.nextInt();
			for(int i = 0; i < number; i++) {
				int c = scanner.nextInt();
				int v = scanner.nextInt();
				int nv = scanner.nextInt();
				int[] night = new int[nv];
				int[][] num = new int[c][c];
				int[][] graph = new int[v][3];
				for(int j = 0; j < v; j++) {
					graph[j][0] = scanner.nextInt() - 1;
					graph[j][1] = scanner.nextInt() - 1;
					graph[j][2] = scanner.nextInt();
				}
				for(int j = 0; j < nv; j++) night[j] = scanner.nextInt() - 1;
				for(int j = 0; j < c; j++) { //初始化图 - 白天的图
					for(int k = 0; k < c; k++)
						if(j != k) num[j][k] = Integer.MAX_VALUE;
						else num[j][k] = 0;
					num[graph[j][1]][graph[j][0]] = num[graph[j][0]][graph[j][1]] = graph[j][2];
				}
				int value = Floyd(num, 1, c);
				System.out.println(value);
				//黑夜后
				int l = 0;
				for(int j = 0; j < c; j++) {//初始化图 - 黑夜时重新建图(因为有多重边)
					for(int k = 0; k < c; k++)
						if(j != k) num[j][k] = Integer.MAX_VALUE;
						else num[j][k] = 0;
					if(j == night[l]) {
						l++;
						continue;
					}else num[graph[j][1]][graph[j][0]] = num[graph[j][0]][graph[j][1]] = graph[j][2];
				}
				for(int j = 0; j < c; j++)
				value = Floyd(num, 1, c);
				System.out.println(value);
			}
		}
	}

	public static int Floyd(int[][] nums, int s, int n) {
		for(int k = 0; k < nums.length; k++) 
			for(int i = 0; i < nums.length; i++) 
				for(int j = 0; j < nums.length; j++) 
					if(nums[i][k] != Integer.MAX_VALUE && nums[k][j] != Integer.MAX_VALUE && nums[i][k] + nums[k][j] < nums[i][j]) 
						nums[i][j] = nums[i][k] + nums[k][j];
		return nums[s - 1][n - 1];
	}
}
发布了233 篇原创文章 · 获赞 254 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/weixin_44485744/article/details/104954998