Tram
题目大意:给你一个图,这个图上有n点和边。点上有开关,开关开始指向一条道路,拨动开关可以使开关指向由开关出发的任意一条路径,读入,a,b,求,至少要拨动几次才能从a点走到b点。
注释:n<=100.
想法:最短路的题,由于n的范围,想采用floyd来处理。首先,说一下读入的方式:第一行3个整数n,a,b,接下来的n行,第i+1行的第一个数表示第i个点出发的有几条边,数据保证每条边会在两个点的读入中出现,而开关默认指向的方向就是所读进来的第二个数,也就是读进来的第一条边。这道题的正解就是强行为边附上边权。如果以这个点出发且开关直接指向这条边就把这条边的边权设为0,如果开关并不指向这条边,但这条边是一条轨道,我们就将这条边的边权设为1。这样,用floyd跑最短路,最后输出map[a][b]即可。
最后,附上丑陋的代码... ...
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int map[101][101];//所记录的边权,以及两点之间的最短路 6 int main() 7 { 8 int n,a,b; 9 int m,x; 10 while(~scanf("%d%d%d",&n,&a,&b)) 11 { 12 memset(map,0x3f,sizeof(map));//每组数据开始前都必须将map数组清零 13 for(int i=1;i<=n;i++) map[i][i]=0;//特判掉a==b的情况 14 for(int i=1;i<=n;i++)//读入所有的轨道 15 { 16 scanf("%d",&m); 17 for(int j=1;j<=m;j++) 18 { 19 scanf("%d",&x); 20 if(j==1) map[i][x]=0; 21 else map[i][x]=1; 22 } 23 } 24 for(int k=1;k<=n;++k)//floyd 25 { 26 for(int i=1;i<=n;++i) 27 { 28 for(int j=1;j<=n;j++) 29 { 30 map[i][j]=min(map[i][j],map[i][k]+map[k][j]); 31 } 32 } 33 } 34 if(map[a][b]==0x3f3f3f3f) printf("-1 ");//如果不行则输出-1 35 else printf("%d ",map[a][b]); 36 } 37 return 0; 38 }
小结,错误:无。