萨格勒布的电车网络由许多交叉路口和连接其中一些的铁路组成。在每个十字路口都有一个开关指向从十字路口出来的轨道之一。当有轨电车进入交叉路口时,它只能按开关所指的方向离开。如果司机想走其他路,他/她必须手动改变开关。
当驾驶员确实从交叉路口 A 开车到交叉路口 B 时,他/她会尝试选择能够最大限度地减少他/她必须手动更换开关的次数的路线。
直接到达w设为0,其余分叉的w就设为1;
编写一个程序,计算从交叉路口 A 行驶到交叉路口 B 所需的最少换道次数。
输入
输入的第一行包含整数 N、A 和 B,由单个空白字符分隔,2 <= N <= 100, 1 <= A, B <= N,N 是网络中的交叉点数,并且交叉点的编号从 1 到 N。
接下来的 N 行中的每一行都包含由单个空白字符分隔的整数序列。第 i 行中的第一个数字 Ki (0 <= Ki <= N-1) 表示离开第 i 个交叉点的轨道数量。接下来的 Ki 数字代表与第 i 个路口直接相连的路口。第 i 个路口的开关最初指向列出的第一个路口的方向。
轨道数就是这个点直接到其他点的边数,开关最初指向所以不用边直接w=0,其余w=1,最后就可以得出改变了几个
输出
输出的第一行也是唯一一行应包含目标最小数。如果没有从 A 到 B 的路由,该行应包含整数“-1”。
样本输入
3 2 1
2 2 3
2 3 1
2 1 2
样本输出
0
思路最短路dij+前向星
#include<iostream>
#include<cstring>
#include<climits>
#include<algorithm>
#include<queue>
#include<stdio.h>
using namespace std;
const int N=120;
int dis[N],head[N],vist[N],cnt=0,s,e;
int inf;
struct Edge{
int to;
int w;
int next;
}edge[N*N];
struct Node{
int id;
int w;
friend bool operator<(const Node& a,const Node& b){
return a.w>b.w;
}
}node;
void add_edge(int u,int v,int w)
{
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void dij()
{
memset(vist,0,sizeof(vist));
memset(dis,0x3f3f3f,sizeof(dis));
inf=dis[0];
priority_queue<Node> yq;
yq.push({s,0});
dis[s]=0;
while(!yq.empty()){
Node cur=yq.top();
yq.pop();
int dang=cur.id;
if(vist[dang]) continue;
vist[dang]=1;
for(int i=head[dang];~i;i=edge[i].next){
int next=edge[i].to;
if(!vist[next]&&dis[next]>dis[dang]+edge[i].w){
dis[next]=dis[dang]+edge[i].w;
yq.push({next,dis[next]});
}
}
}
}
int main()
{
int i,j,n,m,x;
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>s>>e;
memset(head,-1,sizeof(head));
cnt=0;
for(i=1;i<=n;i++){
cin>>m;
if(m==0) continue;
cin>>x;
add_edge(i,x,0);
m--;
while(m){
cin>>x;
add_edge(i,x,1);
m--;
}
}
dij();
if(dis[e]==inf) cout<<"-1"<<endl;//注意没有联通时
else cout<<dis[e]<<endl;
}