萨格勒布的电车网络包括许多交叉路口和连接其中一些的铁路。在每个交叉路口,都有一个开关指向离开交叉路口的一条导轨。有轨电车进入交叉路口时,只能沿开关指向的方向离开。如果驾驶员想走其他路线,则必须手动更改开关。
当驾驶员确实从交叉路口A到交叉路口B行驶时,他/她试图选择一条路线,该路线将最大限度地减少他/她将不得不手动更改开关的次数。
编写一个程序,计算从路口A到路口B所需的最少开关变化次数。
Input
输入的第一行包含整数N,A和B,以单个空白字符分隔,2 <= N <= 100,1 <= A,B <= N,N是网络中的交点数,并且交叉点从1到N编号。
接下来的N行中的每行均包含由单个空白字符分隔的整数序列。第i行中的第一个数字Ki(0 <= Ki <= N-1)表示从第i个交叉点出来的轨道数。下一个Ki数字表示直接连接到第i个交叉点的交叉点。第i个交叉点的开关最初指向列出的第一个交叉点的方向。
Output
输出的第一行和唯一行应包含目标最小值。如果没有从A到B的路线,则该行应包含整数“ -1”。
Sample Input
3 2 1
2 2 3
2 3 1
2 1 2
Sample Output
0
题目大意:
在一个城市里有一个电车道路网,然后有一些岔路口,第一行输入三个数N A B 表示有N个岔路口,需要从A走到B,然后输入n行,对于第 i 行,先输入一个k表示有k个分叉,之后输入k个节点,j1…jk 表示从i -> j 是可行的,但是每个岔路口都有开关,默认的开关打到了每个岔路口的第一个路口,即3 1 2 3 表示有3个路口,可以通向1 2 3 ,但是开关默认指向1。 这句话很重要,影响到后面的建图,对于开关指向的区域可以直接走,对于没有指向的岔路口则需要手动操作,更改开关指向想要去的路口,最后要求输出A 到 B最小的操作数。
解题思路:
比较简单的一道最短路,重要的是读题,建图需要一些技巧,这里的权值就是操作数了。因为起初的开关指向第一个,所以从第二行开始,每行的第一个数权值应该是0,之后都是1才对,建有向边,之后跑spfa即可AC。
Code:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <sstream>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define lowbit(x) x & (-x)
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int N = 1e4 + 50;
const int M = 200 + 50;
int h[N], ne[N], e[N], w[N], idx;
int dis[N];
bool vis[N];
int n, a, b;
void add(int a, int b, int c)
{
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
void spfa(int s)
{
memset(dis, 0x3f, sizeof dis);
dis[s] = 0;
queue<int > q;
q.push(s);
vis[s] = true;
while (!q.empty())
{
int t = q.front();
q.pop();
vis[t] = false;
for (int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if (dis[t] + w[i] < dis[j])
{
dis[j] = dis[t] + w[i];
if (!vis[j])
{
q.push(j);
vis[j] = true;
}
}
}
}
}
int main()
{
scanf("%d%d%d", &n, &a, &b);
memset(h, -1, sizeof h);
for (int i = 1; i <= n; i ++)
{
int k;
scanf("%d", &k);
for (int j = 1; j <= k; j ++)
{
int t;
scanf("%d", &t);
if (j == 1) add(i, t, 0);//第一个权值要建成00
else add(i, t, 1);
}
}
spfa(a);
printf("%d", dis[b] == inf ? -1 : dis[b]);
return 0;
}