对每一个人'用一次BFS,记录其他人与他的距离,并建图。
图建好后,用Prim求最小生成树即为答案。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define M 105
#define VN 2500
#define INF 1000000000
int map[M][M], dist[M][M], que_x[VN], que_y[VN], g[M][M];
int r, c, dir[4][2] = { {-1, 0}, {0, -1}, {1, 0}, {0, 1} };
bool visit[M / 2][M / 2];
void BFS(int x, int y)
{
memset(visit, false, sizeof(visit));
memset(dist, 0, sizeof(dist));
int head, tail, tmp_x, tmp_y, i, j;
visit[x][y] = true; dist[x][y] = 0;
head = 0; tail = 1;
que_x[0] = x; que_y[0] = y;
while (head < tail)
{
tmp_x = que_x[head]; tmp_y = que_y[head]; head++;
for (i = 0; i < 4; i++)
{
int tx = tmp_x + dir[i][0];
int ty = tmp_y + dir[i][1];
if (tx > 0 && tx < r && ty > 0 && ty < c && !visit[tx][ty] && map[tx][ty] >= 0)
{
dist[tx][ty] = dist[tmp_x][tmp_y] + 1;
visit[tx][ty] = true;
que_x[tail] = tx; que_y[tail] = ty; tail++;
if (map[tx][ty] > 0)
{
g[map[x][y]][map[tx][ty]] = dist[tx][ty];
g[map[tx][ty]][map[x][y]] = dist[tx][ty];
}
}
}
}
}
int Prim(int start, int num)
{
bool vis[VN];
int d[VN], i, j, tmp, cur, ans = 0;
memset(vis, false, sizeof(vis));
for (i = 2; i <= num; i++) d[i] = INF;
d[1] = 0;
for (i = 1; i <= num; i++)
{
tmp = INF;
cur = -1;
for (j = 1; j <= num; j++)
{
if (!vis[j] && d[j] < tmp)
{
tmp = d[j];
cur = j;
}
}
if (cur == -1) break;
ans += tmp;
vis[cur] = true;
for (j = 1; j <= num; j++)
if (!vis[j] && g[cur][j] < d[j])
d[j] = g[cur][j];
}
return ans;
}
int main()
{
int n, i, j, num;
char tmp[M / 2];
cin >> n;
while (n--)
{
memset(g, 0, sizeof(g));
cin >> r >> c;
num = 1;
gets(tmp); //在输入的r,c的后面还有空格,gets掉,题目的变态的地方,discuss里面有。
for (i = 0; i < c; i++)
{
gets(tmp);
for (j = 0; j < r; j++)
{
if (tmp[j] == '#') map[i][j] = -1;
else if (tmp[j] == ' ') map[i][j] = 0;
else if (tmp[j] == 'A') map[i][j] = ++num;
else if (tmp[j] == 'S') map[i][j] = 1;
}
}
for (i = 0; i < c; i++)
for (j = 0; j < r; j++)
if (map[i][j] > 0)
BFS(i, j);
cout << Prim(1, num) << endl;
}
return 0;
}