题解:
首先要进行建图,这是一个有向图,把开口的边的权值设为0,没有开口的边的权值设为1。
因为n比较小,可以用dijkstra,也可以用floyed
代码如下:
(1)Dijkstra O(n2)
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#define MAX 105
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n,s,e;//n为路口数,s,e为起点和终点
int dis[MAX],visit[MAX],mp[MAX][MAX];
void dijkstra(int s){
dis[s]=0;
for(int i=0;i<n;i++){
int u=-1,minl=INF;
for(int j=1;j<=n;j++){
if(dis[j]<minl&&visit[j]==0){
u=j;
minl=dis[j];
}
}
if(u==-1) return;
visit[u]=1;
for(int v=1;v<=n;v++){
if(visit[v]==0&&mp[u][v]!=INF){
if(dis[v]>dis[u]+mp[u][v]){
dis[v]=dis[u]+mp[u][v];
}
}
}
}
}
int main(){
scanf("%d%d%d",&n,&s,&e);
for(int i=0;i<MAX;i++){
visit[i]=0;
dis[i]=INF;
}
for(int i=0;i<MAX;i++){
for(int j=0;j<MAX;j++){
mp[i][j]=INF;
}
}
int k,a;
for(int i=1;i<=n;i++){
scanf("%d",&k);
for(int j=0;j<k;j++){
scanf("%d",&a);
if(j==0) mp[i][a]=0;
else mp[i][a]=1;
}
}
dijkstra(s);
if(dis[e]==INF) printf("-1");
else printf("%d",dis[e]);
return 0;
}
(2)Floyed 时间复杂度O(n3)
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<cstring>
#include<vector>
#define MAX 105
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n,s,e,f[MAX][MAX];//f[i][j]表示从i到j的长度
void floyed(){//floyed模板
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(!(i==j||i==k||j==k)){//i不能等于j, j不能等于k, i不能等于k
f[i][j]=min(f[i][k]+f[k][j],f[i][j]);//取最小值
}
}
}
}
}
int main(){
memset(f, INF, sizeof(f));//初始化f
scanf("%d%d%d",&n,&s,&e);
for(int i=1;i<=n;i++){//自己到自己不用按开关
f[i][i] = 0;
}
int k,a;
for(int i=1;i<=n;i++){
scanf("%d",&k);
for(int j=1;j<=k;j++){
scanf("%d", &a);
if(j==1){//第一个赋值为0
f[i][a] = 0;
}
else{
f[i][a] = 1;
}
}
}
floyed();
if(f[s][e]==INF){
printf("-1");
}
else{
printf("%d", f[s][e]);
}
return 0;
}