水题怡情。。。题目大意给你n个点,每个节点有k条出边和一个转换器,要到达节点需要启动转换器才能走到其他的相邻点上,转换器指的方向初始在当前点所指的第一个点。求从起点到终点所需要的最少启动转换器的次数。
之前觉得宽搜一遍应该就可以了,后来仔细想了下,发现只需要把每个点对应转换器的方向那条边赋权值为0,其他的赋权为1然后求一次单源最短路径就可以了,
因为没考虑-1的情况贡献一次WA。。。唉。。。
#include <iostream>
using namespace std;
const int MAXN = 200;
const int MAXM = MAXN*MAXN;
struct node
{
int v, w, next;
}mapp[MAXM];
int id;
int head[MAXN];
void init()
{
id = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int w)
{
mapp[id].v = v, mapp[id].w = w, mapp[id].next = head[u], head[u] = id ++;
}
bool inque[MAXN];
int dist[MAXN];
int Que[10*MAXM];
const int inf = 1 << 30;
void SPFA(int s,int n)
{
for (int i = 1; i <= n; i ++){
inque[i] = false;
dist[i] = inf;
}
dist[s] = 0;
inque[s] = true;
int rear, front;
rear = front = 0;
Que[rear ++] = s;
while (front < rear){
int pre = Que[front ++];
inque[pre] = false;
for (int i = head[pre]; i != -1; i = mapp[i].next){
int v = mapp[i].v;
if (dist[v] > dist[pre] + mapp[i].w){
dist[v] = dist[pre] + mapp[i].w;
if (!inque[v]){
inque[v] = true;
Que[rear ++] = v;
}
}
}
}
}
int main()
{
int n, s, t;
while (scanf("%d%d%d", &n, &s, &t) != EOF){
init();
for (int i = 1; i <= n; i ++){
int a, b, c;
scanf("%d", &a);
int nc = 0;
while (a --){
scanf("%d", &b);
if (!nc)addedge(i, b, 0);
else addedge(i, b, 1);
nc ++;
}
}
SPFA(s, n);
if (dist[t] == inf){
printf("-1\n");
}
else
printf("%d\n", dist[t]);
}
return 0;
}