挺直接的一个题 哎 想复杂了
题意:把n*m矩阵中的字母最小生成树 求它的边权值之和 只有字母可以分叉 多了一个提取点的过程
思路:prime 算法的简单应用
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
char map[55][55];
int node[55][55];
int edge[111][111];
int nsum;
struct Node
{
int x,y;
int t;
};
int m,n;
int dir[4][2]={1,0,-1,0,0,-1,0,1};
void bfs(int x,int y)
{
Node now,next;
queue<Node> q;
now.x=x,now.y=y,now.t=0;
int i,j;
int v[55][55];
q.push(now);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
v[i][j]=999999999;
v[x][y]=0;
while(!q.empty())
{
now=q.front();q.pop();
if(node[now.x][now.y])
edge[node[x][y]][node[now.x][now.y]]=now.t;
for(i=0;i<4;i++)
{
int xx=now.x+dir[i][0];
int yy=now.y+dir[i][1];
if(xx<0||xx>=n||yy<0||yy>=m)
continue;
if(map[xx][yy]=='#')
continue;
if(v[xx][yy]>now.t+1)
{
v[xx][yy]=now.t+1;
next.x=xx;
next.y=yy;
next.t=now.t+1;
q.push(next);
}
}
}
return ;
}
void prime()
{
int sum=0;
int s[111];
memset(s,0,sizeof(s));
int dist[111];
int i,j;
dist[1]=0;
s[1]=1;
for(i=2;i<=nsum;i++)
dist[i]=edge[1][i];
dist[1]=0;
for(i=1;i<=nsum;i++)
{
int min=99999999;
int v=-1;
for(j=1;j<=nsum;j++)
if(!s[j]&&dist[j]<min)
{
min=dist[j];
v=j;
}
if(v==-1) break;
s[v]=1;
sum+=dist[v];
for(j=1;j<=nsum;j++)
if(dist[j]>edge[v][j])
dist[j]=edge[v][j];
}
cout<<sum<<endl;
}
int main()
{
int t,i,j;
char s[100];
scanf("%d",&t);
while(t--)
{
nsum=0;
memset(node,0,sizeof(node));
scanf("%d%d",&m,&n);
gets(s);
for(i=0;i<n;i++)
{
gets(map[i]);
for(j=0;j<m;j++)
{
if(map[i][j]=='S'||map[i][j]=='A')
node[i][j]=++nsum;
}
}
for(i=1;i<=nsum;i++)
for(j=1;j<=nsum;j++)
edge[i][j]=99999999;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(node[i][j])
bfs(i,j);
prime();
}
return 0;
}