1. 题意比较难理解的地方就是会分成几组,其实不用管。因为最小生成树,无论怎么分,无论谁来走,只要最后计算的是最小生成树的最后权值即可。
2. 另一点就是思路。知道肯定要用最小生成树。但是因为每两点间的距离并没有给出来。所以需要先获得距离矩阵。需要用bfs。但是不是传统的bfs,因为这里要求得是全部点间的最短距离。需要使用循环来利用bfs,每次求一个点到其他点间的距离。另外,即使bfs算法本身,也有所不同。这里用了迭代而不是递归。因为要反复用到初始起点,如果用递归的话稍微有点麻烦。然后就是根据起始点到每一个可达点的最短距离(bfs),找出节点间的距离矩阵。而后prim。
3. 当然,由于一定有通路,节省了不少
4. bfs里面和prim里面的dist不要搞混。
5. 参考链接http://blog.csdn.net/lyy289065406/article/details/6645991
6. 340K 16MS
7. 还有一点值得一提,就是这里用了队列。使用队列还实现bfs。因为需要一个遍历所有点的循环。感觉这是一个很巧妙的方法。我们只需要把新点加入,就可以使用bfs了。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
using namespace std;
const int inf = 2600;//无穷
const int maxs = 51;//原始map最值
const int maxs2 = 102;//最小生成树里面的点的最值
char map[maxs][maxs];//原始map
int X[4]={0,1,0,-1};//上下左右
int Y[4]={-1,0,1,0};
int num; //生成树的点数
int n,y,x; //test cases
int dist[maxs2][maxs2];//最短路距离矩阵
//int index ;
//int w,h;
int node[maxs][maxs];//从map到dist的转换
void bfs(int sx, int sy)
{
//直接用递归不合适,因为每次都需要最开始的起始点坐标。
bool flag[maxs][maxs];//标记是否访问过
int queryx[2501];//访问点的队列
int queryy[2501];
int head=0,tail = 0;//头尾指针
queryx[tail] = sx;
queryy[tail++] = sy;//装入起始点
flag[sx][sy] = false;
int mapDist[maxs][maxs];//表示每个可达点到起始点的距离
for(int i = 0; i<maxs; i++)//初始化
{
for(int j = 0; j < maxs; j++)
{
flag[i][j] = true;
mapDist[i][j] = 0;
}
}
while(head<tail)
{
int sx2 = queryx[head];
int sy2 = queryy[head++];
for(int i = 0; i<4; i++)
{
int nextx = sx2 +X[i];
int nexty = sy2+Y[i];
if(flag[nextx][nexty]&&nextx>=0&&nextx<x&&nexty>=0&&nexty<y)
{
if(map[nextx][nexty]!='#')
{
//bfs的每步操作
queryx[tail] = nextx;
queryy[tail++] = nexty;
flag[nextx][nexty] = false;
mapDist[nextx][nexty] =
mapDist[sx2][sy2]+1;
}
if(map[nextx][nexty]=='A')
{
//构建节点距离矩阵
dist[node[sx][sy]][node[nextx][nexty]] = mapDist[nextx][nexty];
}
}
}
}
}
int prim()
{
int s = 1;
int minw ;
bool flag[maxs2];
int minDist[maxs2];
int flagPoint;
int result = 0;
int m = 1;
for(int i = 1; i<maxs2; i++)
{
flag[i] = true;
minDist[i] = inf;
}
while(m!=num)
{
minw = inf;
for(int i = 2; i<=num;i++)
{
if(flag[i]&&minDist[i]>dist[s][i])
{
minDist[i] = dist[s][i];
}
if(flag[i] && minw>minDist[i])
{
minw = minDist[i];
flagPoint = i;
}
}
s = flagPoint;
flag[s] = false;
result +=minw;
m++;
}
return result;
}
int main()
{
//freopen("input.txt","r",stdin);//文件读入
cin>>n;
while(n--)
{
num = 0;
cin>>x>>y;
// index = 0;
char temp[51];
gets(temp);
for(int i = 0; i<y; i++)
{
gets(map[i]);
for(int j = 0; j<x; j++)
{
node[i][j] = 0;
if(map[i][j]=='S')
{
map[i][j] = 'A';
}
if(map[i][j]=='A')
{
node[i][j] = ++num;
}
}
dist[i+1][i+1] = 0;
}
for(int i = 0; i<y; i++)
{
for(int j = 0; j < x; j++)
{
if(node[i][j]!=0)
{
bfs(i,j);
}
}
}
cout<<prim()<<endl;
}
}