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];
}
}