地铁 - Metro - Floyd

 

地铁

时限:最多 40 个用例,2.0 秒 (C/C++),3.0 秒 (Java)

Sherlock 居住的城市有 N 个地铁站。地铁站从 1 到 N 进行编号,地铁线路从 1 到 M 进行编号。给定地铁站数量 N、地铁线路数量 M、出发站和目的地站的组合数量 Q,求从出发站上车到目的地站下车所需的最少换乘次数总和

地铁 - Metro - Floyd

地铁 - Metro - Floyd

 

 

[图]

假设地铁线路图如 [图] 所示,出发站 S 为 2,目的地站 E 为 17。从 S 到 E 的最少换乘次数为 3(2 → 7(换乘)13(换乘)16(换乘) → 17)

 

 [限制条件]

1.地铁站数量 N 为介于 3 到 100,000 之间的整数。

2.地铁线路数量 M 为介于 2 到 300 之间的整数。

3.出发站和目的地站的组合数量 Q 为介于 1 到 10,000 之间的整数。

4.出发站 S 和目的地站 E 的编号为介于 1 到 N 的整数。

5.每条地铁线路上的地铁站点数量 C 为介于 2 到 N 之间的整数。

6.每条地铁线路都是一条连续的线路正反两个方向皆可行驶。

7.经过同一个换乘站的地铁线路最大数量为 10 。

8.从任意地铁站点总是可以前往其他所有站点。

 

[输入]

首先,给定测试用例数量 T,后面接着输入 T 种测试用例。

每个测试用例的第一行,给定地铁站数量 N、地铁线路数量 M、出发站和目的站组合数量 Q。

接下来的 M 行,每行给定一条地铁线路上地铁站数量 C,以及 C 个地铁站的编号,以空格分隔。

接下来的 Q 行,每行给定一对想要求得其最小换乘次数的出发站 S 和目的站 E ,以空格分隔。

 

[输出]

每行输出一个测试用例。每个测试用例,都输出“#x”(x 为测试用例的编号,从 1 开始),以及从出发站到目的站所需的最少换乘次数总和。

 

[输入和输出示例]

(输入)

3

18 5 3

7 2 3 4 7 10 9 8   

4 1 3 6 9             

5 5 6 7 13 14      

4 12 13 15 16      

4 11 16 17 18      

1 8

4 14

2 17

32 5 8

4 19 7 4 1

10 28 5 24 18 10 16 31 2 3 19

8 27 6 21 23 17 20 29 19

9 9 12 8 25 11 14 26 22 19

5 13 30 15 32 19

17 11

25 23

20 8

3 8

18 32

28 16

14 12

20 21

36 5 7

8 4 7 33 34 17 21 9 3

7 8 16 32 2 22 19 3

10 30 14 5 26 24 27 20 36 12 4

8 10 31 23 29 11 18 35 16

7 1 25 28 6 15 13 9

30 1

9 7

6 14

2 31

28 4

5 26

23 36

 

(输出)

#1 5

#2 5

#3 9

 

解决思路:将线路抽象成点,将换乘站点抽象成边,问题变为求多点到多点的最短路径,且数据量为300,可使用Floyd算法。

 

package graph;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

/**
 * 
 * 解决思路:将线路抽象成点,将换乘站点抽象成边,问题变为求多点到多点的最短路径,且数据量为300,可使用Floyd算法。
 * @author XA-GDD
 *
 */
public class Metro_0601 {

	static int INF = Integer.MAX_VALUE>>1;
	static int T,N,M,Q,C;
	static int _Max_N = 100004;
	static int _Max_M = 304;
	static int [][] minDist = new int[_Max_M][_Max_M];
	static ArrayList stationList = new ArrayList();
	static int ANS;
	public static void main(String[] args) throws IOException {
		init();
		
		System.setIn(new FileInputStream("D:\\workspace\\sw_pro\\test_case\\simple_input_0601.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	    StringTokenizer st = new StringTokenizer(br.readLine());
		T = Integer.parseInt(st.nextToken());
	    for(int testCase = 1; testCase<=T;testCase++) {
	    		    	
	    	st = new StringTokenizer(br.readLine());
	    	N = Integer.parseInt(st.nextToken());
	    	M = Integer.parseInt(st.nextToken());
	    	Q = Integer.parseInt(st.nextToken());
	    		    	
	    	for(int m=1;m<=M;m++) {  //地铁线路
	    		st = new StringTokenizer(br.readLine());
	    		C = Integer.parseInt(st.nextToken());
	    		for(int c=1;c<=C;c++) { //地铁站点
	    			int stationNo = Integer.parseInt(st.nextToken());
	    			stationList.get(stationNo).add(m); //每个站点保存对应的线路
	    			
		    		for(int i=0;i<stationList.get(stationNo).size();i++) { //stationList.get(stationNo).size()>0表示当前站点,有多个线路经过,即当前站点为换乘站点
		    			int subwayLine = stationList.get(stationNo).get(i); //站点对应的每个线路
		    			if(subwayLine==m) { //当前线路到当前线路距离为0
		    				minDist[subwayLine][m] = 0; 
		    			}else {//当前线路到其他线路,距离都设为1
		    				minDist[subwayLine][m] = 1; 
		    				minDist[m][subwayLine] = 1;
		    			}
		    		}
	    		}
	    	}

	    	floyd(); //求出任意线路到任意线路的最短路径
	    	for(int q=0;q<Q;q++) {
	    		st = new StringTokenizer(br.readLine());
	    		int start = Integer.parseInt(st.nextToken());
	    		int end = Integer.parseInt(st.nextToken());
	    		int seMinDist = INF;
	    		
	    		//因为给出的数据是站点,而我们求出的是线路到线路的最短路径
	    		//所以要根据站点找到线路,在包含开始站点和结束站点线路的路径中,选择最短的那条
	    		for(int i=0;i<stationList.get(start).size();i++){
	    			int startLine = stationList.get(start).get(i);
	    			for(int j=0;j<stationList.get(end).size();j++){
	    				int endLine = stationList.get(end).get(j);
	    				seMinDist = Math.min(seMinDist, minDist[startLine][endLine]);
		    		}
	    		}
	    		
	    		ANS += seMinDist;
	    	}
	    	System.out.println("#"+testCase+" "+ANS);	    	
	    	clear();
	    }
	        
	}
	
	static void floyd() {
		for(int v=1;v<=M;v++) {
			for(int i=1;i<=M;i++) {
				for(int j=1;j<=M;j++) {
					minDist[i][j] = Math.min(minDist[i][j], minDist[i][v]+minDist[v][j]);
				}
			}
		}
	}

	static void init() {
    	for(int i=0;i<_Max_N;i++) {
    		stationList.add(new ArrayList());
    	}
		for(int i=0;i<_Max_M;i++) {
	    	Arrays.fill(minDist[i], INF);
		} 	
	}

	static void clear() {
		ANS = 0;
		for(int i=0;i<=M+1;i++) {
	    	Arrays.fill(minDist[i], INF);
		}
		
    	for(int i=0;i<=N+1;i++) {
    		stationList.get(i).clear();
    	}
	}
}

  

上一篇:P1359 租用游艇【Floyd】


下一篇:Makefile 中all 和.PHONY的作用