题意:在一个y行 x列的迷宫中,有可行走的通路空格’ ‘,不可行走的墙’#’,还有两种英文字母A和S,现在从S出发,要求用最短的路径L连接所有字母,输出这条路径L的总长度。
从哪个地方出发都是一样的,所以A S一样对待
对每一个A 或S跑一边bfs得到与其他的A或 S 的最短距离 并 记录
最后跑一次最小生成树就好了
输入有点烦。。。多次试验后得到正确输入。。。。。。
gets()
链接:poj 3026
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <vector>
#include <sstream>
#include <queue>
#define ll long long
using namespace std;
const int maxn = 2500 + 10;
const int maxm = 1001000;
const int inf = 0x3f3f3f3f;
int fa[maxn];
int rnk[maxn];
int n, m;
struct node {
int a, b;
int c;
friend bool operator < (node x, node y) {
return x.c < y.c;
}
}q[maxm];
void init(int n) {
for(int i = 0; i <= n; i++) {
fa[i] = i;
rnk[i] = 0;
}
}
int getf(int x) {
if(x != fa[x]) {
fa[x] = getf(fa[x]);
}
return fa[x];
}
void unions(int x, int y) {
x = getf(x);
y = getf(y);
if(x == y) return;
if(rnk[x] < rnk[y]) {
fa[x] = y;
}
else {
fa[y] = x;
if(rnk[x] == rnk[y]) rnk[x]++;
}
}
bool same(int x, int y) {
return getf(x) == getf(y);
}
int kruskal(int n, int m) {
init(n);
sort(q + 1, q + 1 + m);
int ans = 0;
int nedge = 0;
for(int i = 1; i <= m && nedge != n - 1; i++) {
if(getf(q[i].a) != getf(q[i].b)) {
unions(q[i].a, q[i].b);
ans += q[i].c;
nedge++;
}
}
//if(nedge < n - 1) ans = -1;
return ans;
}
char mp[105][105];
int num[105][105];
typedef pair<int, int > P;
int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
int d[105][105];
int d1[2500][2500];
void bfs(int sx, int sy) {
queue<P> que;
memset(d, inf, sizeof(d));
que.push(P(sx, sy));
d[sx][sy] = 0;
while(!que.empty()) {
P p = que.front();
que.pop();
for(int i = 0; i < 4; i++) {
int nx = p.first + dx[i], ny = p.second + dy[i];
if(nx >= 1 && nx <= n && ny >= 0 && ny < m && mp[nx][ny] != '#' && d[nx][ny] == inf) {
que.push(P(nx, ny));
d[nx][ny] = d[p.first][p.second] + 1;
if(mp[nx][ny] == 'A' || mp[nx][ny] == 'S') {
d1[num[sx][sy]][num[nx][ny]] = d[nx][ny];
}
}
}
}
}
int main()
{
int T, kcase = 0;
cin >> T;
while(T--) {
cin >> m >> n;
int k = 0;
char str[111];
gets(str);
memset(num, 0, sizeof(num));
for(int i = 1; i <= n; i++) {
gets(mp[i]);
for(int j = 0; j < m; j++) {
if(mp[i][j] == 'A' || mp[i][j] == 'S') {
num[i][j] = ++k;
}
}
}
memset(d1, inf, sizeof(d1));
for(int i = 1; i <= n; i++) {
for(int j = 0; j < m; j++) {
if(num[i][j]) {
bfs(i, j);
}
}
}
int res = 0;
for(int i = 1; i <= k; i++) {
for(int j = i + 1; j <= k; j++) {
q[++res].a = i;
q[res].b = j;
q[res].c = d1[i][j];
}
}
int ans = kruskal(k, res);
printf("%d\n", ans);
}
return 0;
}