PAT 甲 1131 Subway Map (30 分)

1131 Subway Map (30 分)

題目大意:
給一張地圖,無向,給出n個行線,起點終點,不同行線要通過中轉站轉車,問最少經過多少站到達,如果站數相等,再根據最少轉車次數判斷。
要求輸出站數,和每次轉車的行線,這條行線的起點終點。
輸入:
4
7 1001 3212 1003 1204 1005 1306 7797
9 9988 2333 1204 2006 2005 2004 2003 2302 2001
13 3011 3812 3013 3001 1306 3003 2333 3066 3212 3008 2302 3010 3011
4 6666 8432 4011 1306
3
3011 3013
6666 2001
2004 3001
輸出:
2
Take Line#3 from 3011 to 3013.
10
Take Line#4 from 6666 to 1306.
Take Line#3 from 1306 to 2302.
Take Line#2 from 2302 to 2001.
6
Take Line#2 from 2004 to 1204.
Take Line#1 from 1204 to 1306.
Take Line#3 from 1306 to 3001.
樣例圖:
在這裏插入圖片描述


真是難到我了,尋思着我寫的題也不少了啊,怎麼一點思路沒得,應該是沒喫飯引起的。

這題我開始想着用點來做,但是每個點可能在多個行線上,那麼在判斷的時候這個點u和他所連接的點v,即使開了個二維數組,用來保存每個點所包含的行線,那麼在過從u點到v點,也根本沒有辦法判斷是不是換行線了,因爲就算兩點行線不同,也有可能是一個行線上的,就算兩點行線有相同的,也有可能是不同行線轉來的(4011-1306-7797)到此死機。

這題根本問題我就想錯了,其實可以繼續想,如果從點分配行線不行,那麼從邊呢?4011-1306這條邊是1,1306-7797這條邊是2,那麼就解決了行線處理問題,那麼我們就需要另一個二維數組來保存邊,邊序號就對應點,再查詢兩點邊顏色的時候,對應點來找到邊序號從而找到對應顏色。

因爲找最小而且有環,所以加個vis[]數組,最後別忘記加04d,ok


#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+7,INF = 0x3f3f3f3f;
int line[N][11],link[N][11];//行線顏色,每個點的鄰接點。 
int vis[N],num[N],zpath[N],path[N];//num[u]是u點連出邊的總數 
int n,mzc,mcs;
int getline(int u,int v){
	for(int i=1;i <= num[u];i++){ //暴力找點,通過點找到行線顏色 
		if(link[u][i] == v) return line[u][i];
	}
}
void dfs(int now,int preline,int cs,int zc,int ed){ //當前點,上個行線,坐站數,轉車數,終點 
	path[cs] = now;
	if(cs > mcs || (cs == mcs && zc > mzc) ) return; //剪枝 
	if(now == ed){
		mcs = cs,mzc = zc;
		for(int i=0;i <= cs;i++)
		zpath[i] = path[i];
		return;
	}
	for(int i=1;i <= num[now];i++){
		int v = link[now][i];
		if(!vis[v]){
			vis[v] = 1;
			int line = getline(now,v);
			if(line == preline) dfs(v,line,cs+1,zc,ed);
			else dfs(v,line,cs+1,zc+1,ed);
			vis[v] = 0;
		}
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i <= n;i++){
		int k,u;scanf("%d%d",&k,&u);
		for(int j=2;j <= k;j++){
			int v;scanf("%d",&v);
			link[u][++num[u]] = v;
			line[u][num[u]] = i;
			link[v][++num[v]] = u;
			line[v][num[v]] = i;
			u = v;
		}
	}
	int k;scanf("%d",&k);
	for(int i=1;i <= k;i++){
		memset(vis,0,sizeof vis);
		int st,ed;scanf("%d%d",&st,&ed);
		mcs = mzc = INF;
		dfs(st,-1,0,-1,ed); //這裏我們轉車數要從-1開始,因爲起點行線是-1,那麼不管第二個點是什麼,行線都要+1 
		printf("%d\n",mcs);
		int line1 = getline(zpath[0],zpath[1]);
		for(int i=2;i <= mcs;i++){
			int line2 = getline(zpath[i-1],zpath[i]);
			if(line2 != line1){
				printf("Take Line#%d from %04d to %04d.\n",line1,st,zpath[i-1]);
				line1 = line2;
				st = zpath[i-1];
			}
		}
		printf("Take Line#%d from %04d to %04d.\n",line1,st,ed);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章