P1346 电车

题目描述

在一个神奇的小镇上有着一个特别的电车网络,它由一些路口和轨道组成,每个路口都连接着若干个轨道,每个轨道都通向一个路口(不排除有的观光轨道转一圈后返回路口的可能)。在每个路口,都有一个开关决定着出去的轨道,每个开关都有一个默认的状态,每辆电车行驶到路口之后,只能从开关所指向的轨道出去,如果电车司机想走另一个轨道,他就必须下车切换开关的状态。

为了行驶向目标地点,电车司机不得不经常下车来切换开关,于是,他们想请你写一个程序,计算一辆从路口A到路口B最少需要下车切换几次开关。

输入输出格式

输入格式:

第一行有3个整数2<=N<=100,1<=A,B<=N,分别表示路口的数量,和电车的起点,终点。

接下来有N行,每行的开头有一个数字Ki(0<=Ki<=N-1),表示这个路口与Ki条轨道相连,接下来有Ki个数字表示每条轨道所通向的路口,开关默认指向第一个数字表示的轨道。

输出格式:

输出文件只有一个数字,表示从A到B所需的最少的切换开关次数,若无法从A前往B,输出-1。

输入输出样例

输入样例#1: 
3 2 1
2 2 3
2 3 1
2 1 2
输出样例#1: 
0

一种很好的stl:双向队列,可以同时从队列的前/后 删除/添加元素
思路:似乎有一点类似bfs的spfa,每一次到达一个点,将不用切换开关就能到达的点从队首入队,需要用开关的点从队尾入队。
因为有可能有的点可以由多次不换开关到达而此时的花费小于经过一次変换,所以不能保证队中的点都是最优解,不能当B在队列中出现过就确定B的最优解出现,需要当B成为队首后才能确定A到B的最优解

#include<iostream>
#include<stdio.h>
#include<deque>
#include<cstring>
using namespace std;
deque<int> q;
int i,m,n,j,k[101],a[101][101],s,t,e;
int main()
{
	memset(k,0x3f,sizeof(k));
	scanf("%d%d%d",&n,&s,&t);
	for(i=1;i<=n;i++) 
	{
		scanf("%d",&a[i][0]);
		for(j=1;j<=a[i][0];j++) scanf("%d",&a[i][j]);
	}
	q.push_back(s);
	k[s]=0;
	while(q.size())
	{
		e=q.front();
		q.pop_front();
		if(e==t) 
		{
			printf("%d",k[t]);
			return 0;
		}
		if(k[a[e][1]]>k[e])
		{
			q.push_front(a[e][1]);
			k[a[e][1]]=k[e];
		}
		for(i=2;i<=a[e][0];i++)
		{
			if(k[a[e][i]]>k[e]+1) 
			{
				q.push_back(a[e][i]);
				k[a[e][i]]=k[e]+1;
			}
		}
	}
	printf("-1");
}
原文地址:https://www.cnblogs.com/ZUTTER/p/9310409.html