bfs+prim(最小生成树)
题目中的A和S可同等看待为点,将任意两个点之间的最短路径(也就是边权)通过num遍bfs之后求出来,然后用prim(最小生成树)算法求最小生成树
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
const int maxn=105;
const int inf=0x3f3f3f3f;
int n,m,num;
char s[maxn][maxn];//存储迷宫
int a[maxn][maxn];//标记迷宫里的字符位置
int b[maxn][maxn];//标记该位置是否被访问过,用于广搜的时候
int map[maxn][maxn],dis[maxn],book[maxn];//松弛操作
int next[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
struct node
{
int x;
int y;
int s;
}q[3200],t,f;
void bfs(int x,int y)
{
int head,tail,k,d;
memset(b,0,sizeof(b));
head=0;
tail=1;
t.x=x;
t.y=y;
t.s=0;
b[t.x][t.y]=1;
q[head]=t;
d=1;
while(head<tail)
{
t=q[head];
for(k=0;k<4;k++){
f.x=t.x+next[k][0];
f.y=t.y+next[k][1];
if(a[f.x][f.y]==-1||f.x<0||f.y<0||f.x>=n||f.y>=m||b[f.x][f.y]==1)
continue;
f.s=t.s+1;
if(a[f.x][f.y]>0&&b[f.x][f.y]==0)
{
map[a[x][y]][a[f.x][f.y]]=f.s;
d++;
if(d==num)
return ;
}
b[f.x][f.y]=1;
q[tail]=f;
tail++;
}
head++;
}
}
void prime()
{
int sum=0;
int mi,i,j,u,k;
memset(book,0,sizeof(book));
for(int i=1;i<=num;i++){
dis[i]=map[1][i];
}
book[1]=1;
for(i=1;i<num;i++){
mi=inf;
for(j=1;j<=num;j++){
if(book[j]==0&&dis[j]<mi){
mi=dis[j];
u=j;
}
}
book[u]=1;
sum+=dis[u];
for(k=1;k<=num;k++){
if(book[k]==0&&dis[k]>map[u][k])
dis[k]=map[u][k];
}
}
printf("%d\n",sum);
}
int main()
{
int i,j,t;
scanf("%d",&t);
while(t--){
num=0;
scanf("%d%d\n",&m,&n);
memset(a,0,sizeof(a));
memset(map,0,sizeof(map));
for(i=0;i<n;i++){
gets(s[i]);
}
for(i=0;i<n;i++){
for(j=0;j<m;j++){
if(s[i][j]=='#'){
a[i][j]=-1;
}
if(s[i][j]=='A'||s[i][j]=='S'){
num++;
a[i][j]=num;
}
}
}
for(i=0;i<n;i++){
for(j=0;j<m;j++){
if(a[i][j]>0){
bfs(i,j);
}
}
}
prime();
}
return 0;
}