http://poj.org/problem?id=3026
题意:从S开始找到一条到所有外星人A的通路,使得该通路总长度最短。
分析:暴搜找出所有A/S之间的边,然后用prim把所有最短的边连接起来。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int NM=105;
/*k:外星人的个数,kk:外星人之间所有的边,c[][]:保存第i个外星人的位置*/
int k,kk,ans,n,m,c[55][55],vis[55][55],mark[NM];
int a[4][2]={-1,0,1,0,0,-1,0,1};
char str[55][55];
struct Alien{
int x,y,step;
}q[NM];
struct Node{
int x,y,vau;
}qn[NM*NM];
void BFS()
{
int i,j;
kk=0;
for(i=0;i<k;i++){
queue<Alien>q1;
Alien t,pt;
memset(vis,0,sizeof(vis));
ans=0;
vis[q[i].x][q[i].y]=1;
q1.push(q[i]);
while(!q1.empty())
{
t=q1.front();q1.pop();
if(ans==k-1) break;
for(j=0;j<4;j++){
pt.x=t.x+a[j][0];pt.y=t.y+a[j][1];
if(!vis[pt.x][pt.y] && str[pt.x][pt.y]!='#' &&
pt.x>=0 && pt.x<n && pt.y>=0 && pt.y<m)
{
vis[pt.x][pt.y]=1;
pt.step=t.step+1;
q1.push(pt);
if(str[pt.x][pt.y]=='A' || str[pt.x][pt.y]=='S'){
qn[kk].x=i;qn[kk].y=c[pt.x][pt.y];
qn[kk++].vau=pt.step;
ans++;
}
}
}
}
}
}
bool comp(struct Node A,struct Node B){
return A.vau<B.vau;
}
int prim()
{
int i,res,t;
for(i=0;i<k;i++) mark[i]=1;
sort(qn,qn+kk,comp);
mark[qn[0].x]=0;
res=0;
for(i=0;i<kk;i++){
t=mark[qn[i].x]+mark[qn[i].y];
if(t==1){
res+=qn[i].vau;
mark[qn[i].x]=mark[qn[i].y]=0;
i=0;
}
}
return res;
}
int main()
{
int i,j,len,T;
char s[NM];
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&m,&n);
k=0;
gets(s); //只能用这货读取空格
for(i=0;i<n;i++){
gets(str[i]);
len=strlen(str[i]);
for(j=0;j<len;j++)
if(str[i][j]=='A' || str[i][j]=='S'){
c[i][j]=k;
q[k].x=i;q[k].y=j;q[k++].step=0;
}
}
BFS();
printf("%d\n",prim());
}
return 0;
}