题目描述
在一个神奇的小镇上有着一个特别的电车网络,它由一些路口和轨道组成,每个路口都连接着若干个轨道,每个轨道都通向一个路口(不排除有的观光轨道转一圈后返回路口的可能)。在每个路口,都有一个开关决定着出去的轨道,每个开关都有一个默认的状态,每辆电车行驶到路口之后,只能从开关所指向的轨道出去,如果电车司机想走另一个轨道,他就必须下车切换开关的状态。
为了行驶向目标地点,电车司机不得不经常下车来切换开关,于是,他们想请你写一个程序,计算一辆从路口 AAA 到路口 BBB 最少需要下车切换几次开关。
输入格式
第一行有 333 个整数 N,A,BN,A,BN,A,B(2≤N≤100,1≤A,B≤N2 leq N leq 100, 1 leq A,B leq N2≤N≤100,1≤A,B≤N),分别表示路口的数量,和电车的起点,终点。
接下来有 NNN 行,每行的开头有一个数字 KiK_iKi(0≤Ki≤N−10 leq K_i leq N-10≤Ki≤N−1),表示这个路口与 KiK_iKi 条轨道相连,接下来有 KiK_iKi 个数字表示每条轨道所通向的路口,开关默认指向第一个数字表示的轨道。
输出格式
输出文件只有一个数字,表示从 AAA 到 BBB 所需的最少的切换开关次数,若无法从 AAA 前往 BBB,输出 −1-1−1。
输入输出样例
输入 #1
3 2 1 2 2 3 2 3 1 2 1 2
输出 #1
0
这个题一开始一直在纠结走了一条非指定方向的路后这个路口的指定方向是否还要更改。后来看别人的博客想到了其实这根本没有什么影响。假设再次经过这个路口相当于绕了一个环,这时候指定方向已经更改,如果不按按钮继续走的话还是会绕圈,如果按了按纽换到别的方向肯定不会是最优解了;如果再也不经过这个路口,那么改不改指定方向其实没有区别,这样的话,可以这么建图,把一开始路口连着的指定方向的边的权值设置为0,其它边设置为1,然后跑一遍最短路即可。
注意:1.一个路口连接的道路数可能为0
2.如果到不了的话输出-1
#include <bits/stdc++.h> #define INF 0x3f using namespace std; int n,a,b,tot; const int N=105,M=10005; int head[N],ver[2*M],Next[2*M],edge[2*M]; bool v[N]; int d[N]; priority_queue<pair<int,int> >q; void add(int x,int y,int z) { ver[++tot]=y; edge[tot]=z; Next[tot]=head[x]; head[x]=tot; } void Dijkstra() { int i; memset(d,0x3f3f3f3f,sizeof(d)); memset(v,0,sizeof(v)); d[a]=0; q.push(make_pair(0,a)); while(q.size()) { int x=q.top().second;q.pop(); if(v[x])continue; v[x]=1; int i; for(i=head[x];i;i=Next[i]) { int y=ver[i];int z=edge[i]; if(d[y]>d[x]+z) { d[y]=d[x]+z; q.push(make_pair(-d[y],y)); } } } } int main() { cin>>n>>a>>b; int i; for(i=1;i<=n;i++) { int num; cin>>num; int j; if(num==0)continue;// for(j=1;j<=num;j++) { int temp; scanf("%d",&temp); if(j==1) { add(i,temp,0); } else { add(i,temp,1); } } } Dijkstra(); if(d[b]!=0x3f3f3f3f)cout<<d[b]; else cout<<-1; return 0; }