题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20846
先BFS处理出图,再用kruskal求最小生成树。 poj上一样的题不知为什么死活过不了,就没去做了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int mnx = 110;
const int mxe = 50100;
int dirx[4] = { 1, -1, 0, 0 };
int diry[4] = { 0, 0, 1, -1 };
char map[mnx][mnx];
bool vis[mnx][mnx];
int dis[mnx][mnx];
struct point
{
int x, y;
}p[mnx*mnx];
struct edge
{
int u, v, c;
bool operator < (edge & b) const
{
return c < b.c;
}
}e[mxe];
int fa[mnx];
int n, m;
int c, r;
int find(int t)
{
if (fa[t] != t) fa[t] = find(fa[t]);
return fa[t];
}
int kruskal()
{
sort(e + 1, e + 1 + m);
for (int i = 1; i <= n; i++)
fa[i] = i;
int ret = 0;
for (int i = 1; i <= m; i++)
{
int u = e[i].u, v = e[i].v, c = e[i].c;
u = find(u), v = find(v);
if (u != v)
{
ret += c;
fa[u] = v;
}
}
return ret;
}
int BFS(point s,point en)
{
int ret = 0;
memset(vis, false, sizeof(vis));
memset(dis, 0, sizeof(dis));
queue<point>que;
que.push(s);
vis[s.x][s.y] = true;
dis[s.x][s.y] = 0;
while (!que.empty())
{
point p = que.front();
que.pop();
int x = p.x, y = p.y;
if (x == en.x && y == en.y)
{
return dis[x][y];
}
for (int i = 0; i < 4; i++)
{
int xx = x + dirx[i];
int yy = y + diry[i];
if (xx >= 0 && xx < c && yy >= 0 && yy < r && map[xx][yy] != '#' && !vis[xx][yy])
{
vis[xx][yy] = true;
dis[xx][yy] = dis[x][y] + 1;
point pp;
pp.x = xx;
pp.y = yy;
que.push(pp);
}
}
}
return -1;
}
int main()
{
int casen;
scanf("%d", &casen);
while (casen--)
{
scanf("%d%d", &c, &r);
char ss[10];
gets(ss);
for (int i = 0; i < r; i++)
{
cin.getline(map[i], mnx);
map[i][c];
}
n = 0;
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
{
if (map[i][j] == 'A' || map[i][j] == 'S')
{
n++;
p[n].x = i;
p[n].y = j;
}
}
m = 0;
for (int i = 1; i <= n;i++)
for (int j = i + 1; j <= n; j++)
{
m++;
e[m].u = i;
e[m].v = j;
e[m].c = BFS(p[i], p[j]);
}
int ans = kruskal();
printf("%d\n", ans);
}
}