//题意:只有在点S或点A可以分,求从点S到达所有点A的最少步数。可以用BFS+Prim实现,BFS用来求得任意两点间 ////可达所需的最少步数,从而能构成一张图,两点间的权值就是BFS求得的最少步数。然后用Prim求解。 #include<cstdio> #include<memory> #include<queue> #define MAXX 0x7fffffff using namespace std; int d[4][2]={-1,0,1,0,0,-1,0,1}; int n,m,step[105][105],index[55][55],dist[105]; bool used[55][55],hash[105]; char s[55][55]; struct Point{ int x,y,step; }edge[105]; void BFS(int k,int ans) { queue<Point> q; Point cnt ,tp; tp=edge[k],edge[k].step=0; memset(used,true,sizeof(used)); used[tp.x][tp.y]=false; q.push(tp); while(!q.empty()) { cnt=q.front(); q.pop(); for(int i=0;i<4;i++) { tp.x=cnt.x+d[i][0]; tp.y=cnt.y+d[i][1]; tp.step=1 +cnt.step;//错误代码tp.step=1 +tp.step; if(tp.x>=0&&tp.x<m&&tp.y>=0&&tp.y<n&&used[tp.x][tp.y]&&s[tp.x][tp.y]!='#') { if(s[tp.x][tp.y]=='A') step[k][index[tp.x][tp.y]]=step[index[tp.x][tp.y]][k]=tp.step;//这个里面的所有tp 换成cnt即为我的错误代码 used[tp.x][tp.y]=false;q.push(tp);//忘记tp 进站 } } } } int Prim(int ans) { int i,j,sum=0; for( i=1;i<=ans;i++) { dist[i]=step[1][i]; hash[i]=false; } hash[1]=true; for(i=1;i<=ans;i++) { int max=MAXX,u=1;//为什么要没次初始化u=1 for(j=1;j<=ans;j++) if(dist[j]<max&&!hash[j]) max=dist[j],u=j; sum+=dist[u];hash[u]=true;//错误代码sum+=max for(int k=1;k<=ans;k++) if(step[u][k]<dist[k]&&!hash[k]) dist[k]=step[u][k]; } return sum; } int main() { int T,i,j; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); char buff[101]; int ans=1; gets(buff); for( i=0;i<m;i++) { for( j=0;j<n;j++) { scanf("%c",&s[i][j]); if(s[i][j]=='S') s[i][j]='A',edge[1].x=i,edge[1].y=j,index[i][j]=1; else if(s[i][j]=='A') edge[++ans].x=i,edge[ans].y=j,index[i][j]=ans; } getchar(); } for( i=1;i<=ans;i++) { for( j=1;j<=ans;j++) step[i][j]=MAXX; step[i][i]=0; } for( i=1;i<=ans;i++) BFS(i,ans); printf("%d/n",Prim(ans)); } system("pause"); return 0; }