题很简单,就是求最小生成树的,难点就在于将图转化成边(带权值),就是这一块不好转化。
我想到了用广搜去找每个顶点到其他顶点的距离,但是在代码实现上有些困难,参考了别人的代码后就恍然大悟了,
觉得在prim算法上会很简单,但是同样也遇到了问题,就是在dis[]初始值时候,不知道初始谁了。总认为要先将S(开始搜索的地方)加入第一个dis值中,这样的一个错误的想法就卡住了。
看来还是没有深刻的理解最小生成树含义,从任何一个顶点出发都能到达各个顶点的最小价值。所以S和A的意义是一样的。
还有在进入广搜的时候,我也没有理解透彻!(最后和这个代码从下午死磕到晚上,最后还是别人
给我调试出来的。。。。别人要求我加入他的链接)
在广搜之前就要把求得各个顶点到顶点的最小距离d[]进行初始化,因为每次搜索的是传入的顶点到其它各个顶点的最小距离。
#include<stdio.h>
#include<queue>
#include<string.h>
#define max 1<<31-1
using namespace std;
char map[55][55];
int num_map[55][55];
int vis[55][55];
int time[55][55];
int d[55][55];
int dis[110];
int book[110];
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
int n,m,num;
struct node{
int u;
int v;
node(int uu,int vv):u(uu),v(vv){
}
node(){
}
}no[110];
void bfs(node nd)
{
memset(time,0,sizeof(time));
memset(vis,0,sizeof(vis));
int i,j;
queue<node>Q;
Q.push(nd);
vis[nd.u][nd.v]=1;
while(!Q.empty())
{
node n1=Q.front();
Q.pop();
for(i=0;i<4;i++)
{
int x=n1.u+dx[i];
int y=n1.v+dy[i];
if(x>=0&&x<n&&y>=0&&y<m&&vis[x][y]!=1&&map[x][y]!='#')
{
time[x][y]=time[n1.u][n1.v]+1;
vis[x][y]=1;
Q.push(node(x,y));
if(num_map[x][y]>0)
{
d[num_map[nd.u][nd.v]][num_map[x][y]]=time[x][y];
}
}
}
}
}
int prim()
{
memset(book,0,sizeof(book));
int i,j,count=0,sum=0;
for(i=1;i<=num;i++)
dis[i]=max;
dis[1]=0;
while(count<num)
{
int min=max;
for(i=1;i<=num;i++)
{
if(!book[i]&&dis[i]<min)
{
j=i;
min=dis[i];
}
}
book[j]=1;
count++;
sum+=dis[j];
for(i=1;i<=num;i++)
{
if(!book[i]&&dis[i]>d[j][i])
{
dis[i]=d[j][i];
}
}
}
return sum;
}
int main()
{
int T,i,j;
scanf("%d",&T);
while(T--)
{
memset(num_map,0,sizeof(num_map));
scanf("%d%d",&m,&n);
char str[110];
gets(str);
for(i=0;i<n;i++)
gets(map[i]);
num=0;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
if(map[i][j]=='S'||map[i][j]=='A')
{
num_map[i][j]=++num;
}
}
for(i=1;i<=num;i++)
for(j=1;j<=num;j++)
d[i][j]=max;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(num_map[i][j]>0)
bfs(node(i,j));
printf("%d\n",prim());
}
return 0;
}