【題目】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];
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章