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