[最短路][模版]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

简析

% @约修亚_RK :题目很显然是求最短路,跑DIJK时判断开关是否指向该边即可.这里把它用作"优先队列优化的 Dijkstra 算法" 和 "用Vector实现存图操作" 模版.

贴代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<queue>
 6 #include<vector>
 7 #include<functional>
 8 #define Maxn 20000+10
 9
10 using namespace std;
11 struct edge {
12     int u, v;
13 }edges[Maxn];
14 struct node {
15     int u, d;
16     bool operator<(const node &oth)const {
17         return d > oth.d;
18     }
19 }Temp,now;
20 vector<int>mp[110];
21 priority_queue<node>q;
22
23 bool Book[110];
24 int Dist[110];
25 int main()
26 {
27     /*
28         P1346 电车;
29         ps: 一些细节参考洛谷题解,作者@约修亚_RK
30     */
31     int n, cnt = 0, S, T;
32 fuction_INIT:
33     {
34         scanf("%d%d%d", &n, &S, &T);
35         for (int i = 1, k; i <= n; i++) {
36             scanf("%d", &k);
37             while(k--) {
38                 scanf("%d", &edges[cnt].v);
39                 edges[cnt].u = i;
40                 mp[i].push_back(cnt++);
41             }
42         }
43         memset(Dist, 0x7f, sizeof Dist);
44         Temp.d = 0, Temp.u = S;
45     }
46 faction_DIJKSTRA:
47     {
48         q.push(Temp);
49         while (!q.empty()) {
50             now = q.top(); q.pop();
51             if (Book[now.u]) continue;
52             Book[now.u] = true;
53             for (unsigned int k = 0; k < mp[now.u].size(); k++) {
54                 edge &e = edges[mp[now.u][k]];
55                 if (now.d + (k != 0) < Dist[e.v]) {//开关默认指向第一个数字表示的轨道.
56                     Temp.u = e.v, Temp.d = Dist[e.v] = now.d + (k != 0);
57                     q.push(Temp);
58                 }
59             }
60         }
61     }
62 faction_OUT:
63     {
64         printf("%d", Dist[T] == 0x7f7f7f7f ? -1 : Dist[T]);
65         return 0;
66     }
67 }
				
时间: 2024-08-24 20:53:03

[最短路][模版]P1346 电车的相关文章

洛谷P1346 电车

P1346 电车 236通过 757提交 题目提供者yeszy 标签图论福建省历届夏令营 难度普及/提高- 提交该题 讨论 题解 记录 最新讨论 解不好啊,快疯了!!哪位大… 求解:为何除了-1的点之外都… 为什么会超时…… 题目描述 在一个神奇的小镇上有着一个特别的电车网络,它由一些路口和轨道组成,每个路口都连接着若干个轨道,每个轨道都通向一个路口(不排除有的观光轨道转一圈后返回路口的可能).在每个路口,都有一个开关决定着出去的轨道,每个开关都有一个默认的状态,每辆电车行驶到路口之后,只能从开

luogu P1346 电车 最短路

显然结论 一个点不会经过了两次,一个阀门不会反复开关.第一条边为0,其余边为1. 1 #include <cstdio> 2 #include <queue> 3 using namespace std; 4 int head[120],dis[120],to[30000],nxt[30000],val[30000]; 5 bool vis[120]; 6 int cnt,s,t,n; 7 8 struct pot 9 { 10 int x,dis; 11 pot (int _x

次短路 + 第K短路 模版

虽然从字面上看,次短路和第2短路是一样的.但是我在题目中遇到的却不是这样的. 在有些题目中,需要判断次短路是否存在.比如说,u.v之间只有一条路径.那么只有最短路.次短路是不存在的.这时候,解题方法是先求出最短路,然后枚举删除最短路径中的边,然后求最小值.题目可以看poj3986. 第K短路的实现是 SPFA + A* 算法. A*算法通过一个估价函数f(h)来估计途中的当前点p到终点的距离,并由此决定它的搜索方向,当这条路径失败时,它会尝试其他路径.对于A*,估价函数 = 当前值 + 当前位置

最短路模版 (dijkstra&amp;&amp;flody)

1.dijkstra void dijkstra(int x,int n)//x表示起点,n表示一共的数量 { int min=0,p=0; for(int i=1;i<=n;i++) { dis[i]=map[x][i]; visited[i]=0; } visited[x]=1; for(int i=1;i<=n;i++) { min=inf; for(int j=1;j<=n;j++) { if(!visited[j]&&dis[j]<min) { min=d

P1346 电车

懂得怎么建图就好做了,有些路权值为1,有些为0 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=10000; 4 const int maxm=50000; 5 const int INF=1e9; 6 7 inline int read() 8 { 9 int x=0,k=1;char c=getchar(); 10 while(c<'0'||c>'9') {if(c=='-') k=-1;c=g

最短路总结

最近过的最短路题目稍微总结一下,顺便写一下模板,最短路算法众多有floyd.dij.bell-man.spfa,速度最快就是dij+优先队列或者dij+堆排序,spfa理论上很快o(ke)但实际并不一定不过spfa传说中有一个很NB用处就是处理带负权回路. 邻接表VS邻接矩阵:根据写题经验,如果可以用矩阵那一定是首选,矩阵速度比表快而且题目出现多重边时矩阵很好解决. 今天不小心又遇见正向表与最短路图(HDU2433),感觉很兴奋哈,通宵刷题的感觉很好玩!遗憾的是hdu1385还没过,那是一题最短

【2019寒假集训DAY2】图论

Dijkstra 条件:无负权:时间:O(n*n) 详解+模板: https://www.cnblogs.com/jason2003/p/7222182.html (模板)P1821 [USACO07FEB]银牛派对Silver Cow Party:https://www.luogu.org/recordnew/show/12339877 void dj(){ for(int i=1;i<=m;i++) if(i!=k)dis[i]=M; for(int i=1;i<=m;i++){ int

xdoj

1000.a+b. #include<bits/stdc++.h> using namespace std; int a,b; int main() { ios::sync_with_stdio(false); while(cin >> a >> b) cout << a+b << endl; return 0; } 1001.直接开数组回爆内存,于是自己开个一维数组存放元素,大小需要自己斟酌.(或者动态数组) 直接处理对应位置,根据最后对应的位

【Luogu1359】租用游艇

点此进入原题 算法:简单线性DP 题解: 本题是最短路模版题,也是线性DP的模版题啊--(自己胡诌的--) 设f[i]为到第i个站的最小租金,则 f[1]=0, f[i]=min{f[j]+r[j][i]}(1≤j<i) (r[i][j]表示从i到j的租金,输入给出) 就是这样,也很好理解哟~~ 代码: #include <cstdio> const int N = 233; #define INF 23333333 int r[N][N], f[N], n; inline int mn