2021-08-26

萨格勒布的电车网络由许多交叉路口和连接其中一些的铁路组成。在每个十字路口都有一个开关指向从十字路口出来的轨道之一。当有轨电车进入交叉路口时,它只能按开关所指的方向离开。如果司机想走其他路,他/她必须手动改变开关。

当驾驶员确实从交叉路口 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;			
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值