BFS+prim求MST,先对图做一遍bfs,找到图中各个字母之间的最短距离,不一定是以S为起点,以其他点为起点也可以。
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stack>
#include<queue>
#include<math.h>
#include<cstdio>
using namespace std;
const int inf=0xffffff;
struct node
{
int x,y,step;
};
int op[4][2]={{1,0},{0,-1},{-1,0},{0,1}};
char cmap[200][200];
int map[200][200];
int vis[200][200];
int dist[200];
int mark[200];
int d[200][200];
int n,m;
bool judge(node a)
{
return (a.x>=0 && a.x<m && a.y>=0 && a.y<n);
}
void bfs(int sor,int x,int y)
{
memset(vis,0,sizeof(vis));
queue<node> q;
while(!q.empty()) q.pop();
node s;
s.x=x;
s.y=y;
s.step=0;
vis[x][y]=1;
q.push(s);
while(!q.empty())
{
node u,t;
u=q.front();
q.pop();
int yy=map[u.x][u.y];
if(yy>=0)
d[sor][yy]=d[yy][sor]=u.step;
for(int i=0;i<4;i++)
{
t.x=u.x+op[i][0];
t.y=u.y+op[i][1];
t.step=u.step+1;
if(judge(t) && !vis[t.x][t.y] && cmap[t.x][t.y]!='#')
{
vis[t.x][t.y]=1;
q.push(t);
}
}
}
}
int prim(int N)
{
int ret=0;
memset(dist,inf,sizeof(dist));
memset(mark,0,sizeof(mark));
for(int i=0;i<N;i++)
dist[i]=d[0][i];
dist[0]=0;
mark[0]=1;
while(1)
{
int min=inf;
int v=-1;
for(int i=0;i<N;i++)
if(!mark[i] && dist[i]<min)
{
min=dist[i];
v=i;
}
if(v==-1) break;
ret+=min;
mark[v]=1;
for(int i=0;i<N;i++)
{
if(!mark[i] && dist[i]>d[v][i] && i!=v)
dist[i]=d[v][i];
}
}
return ret;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char c[55];
memset(map,-1,sizeof(map));
scanf("%d%d",&n,&m);
gets(c);
for(int i=0;i<m;i++)
gets(cmap[i]);
int cnt=0;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
if(cmap[i][j]=='A' || cmap[i][j]=='S')
map[i][j]=cnt++;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
if(map[i][j]>=0)
bfs(map[i][j],i,j);
printf("%d\n",prim(cnt));
}
return 0;
}